gifts2017

Прием СМС из 1С

Опубликовал Сергей (Sybr) в раздел Программирование - Практика программирования

Написано много статей по отправке и приему смс в 1С, но большинство из них используют сторонние сервисы, программы или вк.  Не так давно пришлось решать необычную задачу по приему смс получилось обойтись только usb модемом  и платформой 1С.  Хочу поделиться этим опытом с сообществом.

   Я не сторонник использовать 1С для целей отличных от автоматизации учета, но руководство поставило задачу видеть полученные смс именно в 1С Бухгалтерии и выполнять определенные действия при получении.

   Для реализации этой идеи был куплен самый дешевый USB модем и сим карта. До этого опыта работы с модемом или телефоном из 1С я не имел, но знал, что взаимодействовать с устройством можно отправляя АТ команды на com порт, к которому он подключен. После недолгого поиска в интернете необходимые команды были найдены, но выяснилось, что в современных версиях виндовс - Телнет, через который можно было бы оттестировать процедуру, уже не входит в поставку. Пришлось воспользоваться одной из альтернатив. Мой выбор пал на Putty, маленькая, бесплатная портабл программка.

Окно Putty

 

Совершив нехитрые настройки, открываем порт и видим долгожданное окно консоли.

Консоль

 

Отправляем поочередно команды:

 

AT+CMGF=1 – устанавливает текстовый режим работы, от этой команды зависит формат в котором модем будет присылать список смс. 0-цифровой, 1-текстовый. 

 

AT+CMGL="ALL" – получает все сообщения, которые есть в памяти сим карты.

 

После выполнения команды, видим на экране список смс в виде: 

+CMGL: 5,"REC UNREAD","+7920631**93",,"14/10/30,12:20:29+12"

041204410435043C0020043F04400438043204350442002E0020042D0442043E00200441043C04410020043104430434043504420020043F0440043E0447043804420430043D043E002004380437002000310441 


    Если с первой строкой все понятно:номер смс в памяти сим, статус, телефон отправителя и дата/время сообщения, то сам текст сообщения- закодирован.

  Прочитав кучу информации по структуре смс, понял, что сообщения написанные на кириллице кодируются юникодом, блоками по 4 шестнадцатеричных символа.

   Первое, что нужно сделать для декодирования перевести число из шестнадцатеричной системы счисления в десятичную, но в 1С нет стандартной процедуры перевода. Решив не изобретать велосипед самому, нашел изящное решение на данном сайте, за которое большое спасибо автору.

Функция ИзХСчислВЧисло(аф,Шаблон)
	аф = ВРег(аф); // на всякий случай.
	ДлинаШаблона = СтрДлина(Шаблон);	
	ДлинаСтроки = СтрДлина(аф);
	Рез = 0;	
	Для ТекСимвол = 1 По ДлинаСтроки Цикл
		ОбрабатываемыйСимвол = Сред(аф, ТекСимвол,1);
		ПозицияВШаблоне = Найти(Шаблон,ОбрабатываемыйСимвол)-1;
		Рез = Рез * ДлинаШаблона + ПозицияВШаблоне;
	КонецЦикла;	
	Возврат(Рез);	
КонецФункции

Переводим из шестнадцатиричное число в десятичное и получаем символ соответствующий этому коду. В целом процедура выглядит так:

Процедура Конвертация()
Результат="";	
 ДлиннаРез=Цел(СтрДлина(ИсходныйТекст)/4);
 Для й=0 по ДлиннаРез-1 Цикл
    Результат=Результат+ПолучитьСимвол(Сред(ИсходныйТекст,й*4+1,4)); 
 КонецЦикла;
КонецПроцедуры
Функция ПолучитьСимвол(ИсхСтр)
 КодСимв=ИзХСчислВЧисло(ИсхСтр,"0123456789ABCDEF");
 ЧислоКодСивола=Число(КодСимв);
 Возврат Символ(ЧислоКодСивола);
КонецФункции

Обработка для проверки конвертации

 

 Итак, процедура конвертации работает, осталось отправить из АТ команды на com порт, получить ответ, преобразовать в кириллический текст и обрабатывать по своему усмотрению. Существует несколько вариантов чтения ком порта, я выбрал через FileSystemObject.

 Попытка 
     FSO = Новый COMОбъект("Scripting.FileSystemObject");
 Исключение
   Сообщить(ОписаниеОшибки());
   Возврат;
  КонецПопытки;
//Отправка команды
	file=fso.CreateTextFile(КомПорт); 
	file.WriteLine("AT+CMGF=1");
	file.WriteLine("AT+CMGL=""ALL""");
	file.Close();
//Чтение результата:
  file=fso.OpenTextFile(КомПорт); //Открываем файл в режиме "только чтение" 
  Пока ИСТИНА Цикл
    Если  Найти(Стр,"BOOT")<>0 или  Найти(Стр,"ERROR")<>0 Тогда
	Прервать;
    КонецЕсли;
  стр=file.ReadLine();
  КонецЦикла;

  file.Close();

 

 Создаем регламентное задание, которое через заданные промежутки времени выполняет данную процедуру и можно получать смс прямо в 1С. 

   Через некоторые время столкнулся с проблемой переполнения памяти сим карты, поэтому после успешного чтения отправляю команду на удаление смс.

file=fso.CreateTextFile(КомПорт); 
	Для Каждого Эл Из МассивСМС Цикл
		file.WriteLine("AT+CMGD="+Эл.НомерСМС);
	КонецЦикла;
file.Close();

  Вот собственно и все. Осталось написать процедуру обработки получения смс, свою приводить не буду, так как она  узкоспециализированая, но видится много вариантов развития механизма, например отправлять назад на телефон или email конечное сальдо по номеру присланного счета или выводить смс всем сотрудникам - как оповещение от директора, вообщем все на что хватит фантазии.

Код процедуры, которая добавляет СМС в справочник. В конфигурацию должен быть добавлен справочник СМСсообщения  с реквизитами строкового типа : НомерСМС, Телефон, Дата, Сообщение. И константа, в которой храниться номер ком порта модема.

Процедура ПроверкаСМС() Экспорт
	НомерПорта=Константы.КомПортМодема.Получить();
	Если Не ЗначениеЗаполнено(НомерПорта) Тогда
		Сообщить("Не задан ком порт для модема!");
		Возврат;
	КонецЕсли;
	
	КомПорт = "\\.\COM"+НомерПорта;
	
	Попытка 
		FSO = Новый COMОбъект("Scripting.FileSystemObject");
	Исключение
		Сообщить(ОписаниеОшибки());
		Возврат;
	КонецПопытки;
	СтрокаНаОтправку="AT+CMGF=1";
	file=fso.CreateTextFile(КомПорт); 
	file.WriteLine("AT+CMGF=1");
	file.WriteLine("AT+CMGL=""ALL""");
	file.Close();
	МассивСМС=Новый Массив;
	Стр="нач. знач";
	file=fso.OpenTextFile(КомПорт); //Открываем файл в режиме "только чтение" 
	Пока ИСТИНА Цикл
		Если  Найти(Стр,"BOOT")<>0 или  Найти(Стр,"ERROR")<>0 Тогда
			Прервать;
		КонецЕсли;
		стр=file.ReadLine();
		Если Найти(Стр,"+CMGL:") Тогда //строка с заголовком сообщения
			СтруктураЗаголовка=РазобратьСтрокуЗаголовка(Сред(Стр,7));
			Если СтруктураЗаголовка=Неопределено Тогда
				Сообщить("Неверный формат заголовка сообщениея!");
				Прервать;
			КонецЕсли;
			ТекстСообщения=file.ReadLine();
			Результат="";	
			ДлиннаРез=Цел(СтрДлина(ТекстСообщения)/4);
			Для й=0 по ДлиннаРез-1 Цикл
				Результат=Результат+ПолучитьСимвол(Сред(ТекстСообщения,й*4+1,4)); 
			КонецЦикла;
			СтруктураЗаголовка.Вставить("Сообщение",Результат);
			МассивСМС.Добавить(СтруктураЗаголовка);                          
		КонецЕсли;
	КонецЦикла; 
	file.Close();
	file=fso.CreateTextFile(КомПорт); 
	Для Каждого Эл Из МассивСМС Цикл
		file.WriteLine("AT+CMGD="+Эл.НомерСМС);
	КонецЦикла;
	file.Close();
	Для Каждого  Эл из МассивСМС Цикл
		НовСмс=Справочники.СМСсообщения.СоздатьЭлемент();
		ЗаполнитьЗначенияСвойств(НовСмс,Эл);
		НовСмс.Записать();
	КонецЦикла
КонецПроцедуры


Функция ИзХСчислВЧисло(аф,Шаблон)
	аф = ВРег(аф); // на всякий случай.
	ДлинаШаблона = СтрДлина(Шаблон);
	
	ДлинаСтроки = СтрДлина(аф);
	Рез = 0;
	
	Для ТекСимвол = 1 По ДлинаСтроки Цикл
		ОбрабатываемыйСимвол = Сред(аф, ТекСимвол,1);
		ПозицияВШаблоне = Найти(Шаблон,ОбрабатываемыйСимвол)-1;
		Рез = Рез * ДлинаШаблона + ПозицияВШаблоне;
	КонецЦикла;
	
	Возврат(Рез);
	
КонецФункции


Функция ПолучитьСимвол(ИсхСтр)
	КодСимв=ИзХСчислВЧисло(ИсхСтр,"0123456789ABCDEF");
	ЧислоКодСивола=Число(КодСимв);
	Возврат Символ(ЧислоКодСивола);
КонецФункции

Функция РазобратьСтрокуЗаголовка(СтрЗаголовка)
	СтруктураЗаголовка=Новый Структура;
	МассивСтрок=ОбщегоНазначения.РазложитьСтрокуВМассивПодстрок(СтрЗаголовка);
	Если МассивСтрок.Количество()<6 Тогда
		Возврат Неопределено;
	КонецЕсли;
	Телефон=СтрЗаменить(МассивСтрок[2],"""","");//удаляем кавычки
	ДатаСМС=СтрЗаменить(МассивСтрок[4],"""","");
	СтруктураЗаголовка.Вставить("НомерСМС",МассивСтрок[0]);
	СтруктураЗаголовка.Вставить("Телефон",Телефон);
	СтруктураЗаголовка.Вставить("Дата",ДатаСМС);
	Возврат СтруктураЗаголовка;
КонецФункции	

См. также

Подписаться Добавить вознаграждение

Комментарии

1. Kostya Zhurov (It-developer) 31.10.14 12:54
2. Vlad Bill (Bad_Developer) 31.10.14 14:37
Хорошая статья, хотел добавить, что стандартный telnet client включается в современных системах через Windows Features (Компоненты системы)
3. VVV (V_V_V) 31.10.14 18:11
"поэтому после успешного чтения отправляю команду на удаление смс" - я так понимаю пример выцарапан из работающего кода. Откуда взялся "МассивСМС" ?
4. Сергей (Sybr) 31.10.14 19:05
(3) МассивСМС мы заполняем в цикле чтения, если нужно могу добавить полный код регламентной процедуры.
5. VVV (V_V_V) 31.10.14 19:14
(4) Sybr, вот это я и имел ввиду. Просто ваш МассивСМС по-ходу содержит какие-то Соответствия или еще чего - новичкам будет печально использовать этот код :)
6. Юрий (karetir) 31.10.14 19:26
7. Сергей (Sybr) 31.10.14 19:32
(5) Да, это структура. Добавил полный код, который добавляет смс в справочник, теперь должно быть понятнее.
8. Николай (nipil) 01.11.14 17:04
Хорошая полезность!
- "Дайте две"!
9. Призрак (davdykin) 01.11.14 20:04
Спасибо за статью. Актуальная тема с изящным решением.
10. Pavel Fomin (Pasha1st) 01.11.14 22:01
Совместимость с разными модемами не проверяли?
Кстати, большинство современных модемов создает несколько COM-портов, что позволяет управлять модемом (в т.ч. работать с СМС) при установленном соединении с интернетом
11. Сергей (Sybr) 02.11.14 06:25
(10) Точно, забыл написать, что у меня работает это все на модеме huawei e173, на других не проверял, но думаю способ достаточно универсальный.
12. shurik_shurik (shurik_shurik) 03.11.14 09:11
Красиво! Кстати, по поводу универсальности: я когда-то давно этим вопросом занимался еще на DELPHI с разными модемами: стандарт этих команд общепринят.
Еще бы процедуру отправки СМС через модем.... Было-бы очень здорово!
P.S. Проверяли на составных СМС? это когда текста много и СМС состоит из нескольких сообщений.
13. Сергей Валутин (Bacemo) 03.11.14 12:25
А я не понимаю, зачем СМС получать в 1С -:)))
14. VVV (V_V_V) 03.11.14 16:41
(7) Sybr, Пока что мне не актуально, только рассылаю СМС, но все равно плюсану.
(12) shurik_shurik, если по России, то есть куча готовых решений через сервисы рассылки. Например в библиотеке стандартных подсистем зашито 2 варианта. По Украине тут проскакивало (сочтут за рекламу, поиск поможет), сам использую. Стоимость одного СМС дешевле через сервис рассылки, хотя может какие-то льготные пакеты и можно найти...
15. Сергей (Sybr) 03.11.14 17:33
(12) Я отправлял через веб сервисы, важно было писать название организации вместо номера. Готового кода для отправки через модем у меня нет, но принцип там такой же.
(13) Разные бзики бывают у руководства )
16. Сергей Галюк (dj_serega) 05.11.14 08:47
Крутая штука, но вот пригодится или нет это уже вопрос :)
17. Данила Елистратов (CagoBHuK) 05.11.14 09:50
Научился работать с ком-портом и изучил протокол АТ для модема?
18. Сергей (Sybr) 05.11.14 14:41
(17) Это к чему? Намек, что не было смысла писать о таких элементарных вещах? Самое сложно было преобразовать кодировку в русский текст, а отправлять команды на ком порт трудностей не составляет.
19. Serg Ershov (ershz) 06.11.14 11:19
Клиент telnet, который начиная с Vista, по умолчанию не устанавливается и требует включения через appwiz.cpl, в принципе не умеет работать с ком-портом.
Вероятно, имелся в виду гипертерминал (HyperTerm), который тоже исключен из поставки.
Putty - правильный выбор :)
20. Антон Антонов (monkbest) 06.11.14 13:23
Классно, я плюсанул, но в начале статьи обманул:
получилось обойтись только usb модемом и платформой 1С

Putty - часть платформы?
21. Сергей (Sybr) 07.11.14 09:22
(20) Она была нужна, только для тестривания АТ команд. Можно было бы обойтись и без неё)
22. Ридван (утюгчеловек) 16.11.14 13:39
Очень интересная статья. Поставил бы два плюса, если бы мог.

для въедливых, поясните пожалуйста: usb-модем это тот, в который нужно засунуть сим-карту? Просто не очевидный момент, в поисковиках вижу "тип: GSM", это однозначно указывает на необходимость сим-карты для работы или нет?

Предположим, у меня есть та самая "несовременная" версия винды, и я хочу проверить команды модема. Как это сделать? Куда копать? В настройках HyperTerminal ничего криминального не нашел. Вижу консоль программы, и до свидания. Просто слова
Совершив нехитрые настройки, открываем порт и видим долгожданное окно консоли.

для меня лично напомнило "путем нехитрых преобразований" в книгах Ландау по физике, где трехэтажный интеграл преобразуется в компактный одноэтажный. Нужно пояснение
23. Сергей (Sybr) 17.11.14 12:52
(22) Да, тут конечно имеется модем с сим картой. Сначала необходимо установить драйвера для модема, обычно они на флэш памяти самого модема лежат и устанавливаются из автозапуска. В гипертерминале нужно выбрать этот установленный модем, нет сейчас его под рукой, не могу сказать как там точно это делать. Попробуйте скачать Путти, там сложностей никаких нет точно, выбирается только ком порт и скорость.
24. Сергей Самошин (saiten) 17.11.14 13:21
Кстати, писать в ком-порт можно и стандартными средствами 1С:
	ком = новый ЗаписьТекста("//./COM12",КодировкаТекста.UTF16);
	ком.ЗаписатьСтроку(СтрокаДляЗаписиВПорт);

Читать, наверное. тоже можно, но я не пробовал.
25. Сергей (Sybr) 17.11.14 14:42
(24) У меня почему-то этот способ работал очень долго и постоянно зависал, изначально тоже так побывал, но остановился на варианте из статьи.
26. Максим Кышларь (new_creation) 27.02.15 02:55
Спасибо за статью. Думаю скоро пригодится.
27. German Derkachenko (SoftLeon) 01.03.15 11:27
Спасибо за статью, очень актуально!!!
28. Сергей (Sybr) 03.03.15 08:07
29. Максим Кышларь (new_creation) 04.03.15 20:40
Sybr, с помощью твоего кода пытаюсь получить смс-ки. При попытке считывании строк методом ReadLine Платформа виснет, не знаешь почему?
30. Сергей (Sybr) 05.03.15 14:38
(29) new_creation, а в консоли попробовал подключиться к модему, происходит чтение? Скорее всего, если виснет, то никаких сообщений в данный момент с компорта нет.
31. Максим Кышларь (new_creation) 06.03.15 02:28
(30) Sybr, да. Смотрю через консоль - сообщения есть (3). Скажи, а ты настраивал модем ат-командами (например команда есть, чтоб он работал в режиме "только модем" и т.п.)? Это на сервере MS 2008... Как ты сделал, чтобы у тебя появилась строка Modem в Putty? У меня ее нет (Default...). Еще Putty портабельная, ничего? Еще возможно модем подключен через роутер (по сети настраиваю). Я в этих портах, роутерах не понимать особо. Подскажи, если знаешь... спасибо заранее.
32. Сергей (Sybr) 11.03.15 09:49
(31) Модем не настраивал, работает "как есть". Строка Modem это просто название настроек у меня. У меня тоже была портабл версия. А на счет модема через роутер я не понял, это же USB модем, он у тебя в роутер воткнут? Если так, то странно, что Putty видит его. Подразумевается, что модем должен быть в USB, с эмуляцией com порта.
Для написания сообщения необходимо авторизоваться
Прикрепить файл
Дополнительные параметры ответа