Каталог решений - Прием СМС из 1С

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

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

В наличии

Написано много статей по отправке и приему смс в 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]);
	СтруктураЗаголовка.Вставить("Телефон",Телефон);
	СтруктураЗаголовка.Вставить("Дата",ДатаСМС);
	Возврат СтруктураЗаголовка;
КонецФункции	

has been added to your cart:
Оформление заказа