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

33 Comments

  1. It-developer

    Красавчик

    Reply
  2. Bad_Developer

    Хорошая статья, хотел добавить, что стандартный telnet client включается в современных системах через Windows Features (Компоненты системы)

    Reply
  3. V_V_V

    «поэтому после успешного чтения отправляю команду на удаление смс» — я так понимаю пример выцарапан из работающего кода. Откуда взялся «МассивСМС» ?

    Reply
  4. Sybr

    (3) МассивСМС мы заполняем в цикле чтения, если нужно могу добавить полный код регламентной процедуры.

    Reply
  5. V_V_V

    (4) вот это я и имел ввиду. Просто ваш МассивСМС по-ходу содержит какие-то Соответствия или еще чего — новичкам будет печально использовать этот код 🙂

    Reply
  6. Sybr

    (5) Да, это структура. Добавил полный код, который добавляет смс в справочник, теперь должно быть понятнее.

    Reply
  7. nipil

    Хорошая полезность!

    — «Дайте две»!

    Reply
  8. davdykin

    Спасибо за статью. Актуальная тема с изящным решением.

    Reply
  9. Pasha1st

    Совместимость с разными модемами не проверяли?

    Кстати, большинство современных модемов создает несколько COM-портов, что позволяет управлять модемом (в т.ч. работать с СМС) при установленном соединении с интернетом

    Reply
  10. Sybr

    (10) Точно, забыл написать, что у меня работает это все на модеме huawei e173, на других не проверял, но думаю способ достаточно универсальный.

    Reply
  11. shurik_shurik

    Красиво! Кстати, по поводу универсальности: я когда-то давно этим вопросом занимался еще на DELPHI с разными модемами: стандарт этих команд общепринят.

    Еще бы процедуру отправки СМС через модем…. Было-бы очень здорово!

    P.S. Проверяли на составных СМС? это когда текста много и СМС состоит из нескольких сообщений.

    Reply
  12. Bacemo

    А я не понимаю, зачем СМС получать в 1С -:)))

    Reply
  13. V_V_V

    (7) Пока что мне не актуально, только рассылаю СМС, но все равно плюсану.

    (12) shurik_shurik, если по России, то есть куча готовых решений через сервисы рассылки. Например в библиотеке стандартных подсистем зашито 2 варианта. По Украине тут проскакивало (сочтут за рекламу, поиск поможет), сам использую. Стоимость одного СМС дешевле через сервис рассылки, хотя может какие-то льготные пакеты и можно найти…

    Reply
  14. Sybr

    (12) Я отправлял через веб сервисы, важно было писать название организации вместо номера. Готового кода для отправки через модем у меня нет, но принцип там такой же.

    (13) Разные бзики бывают у руководства )

    Reply
  15. dj_serega

    Крутая штука, но вот пригодится или нет это уже вопрос 🙂

    Reply
  16. CagoBHuK

    Научился работать с ком-портом и изучил протокол АТ для модема?

    Reply
  17. Sybr

    (17) Это к чему? Намек, что не было смысла писать о таких элементарных вещах? Самое сложно было преобразовать кодировку в русский текст, а отправлять команды на ком порт трудностей не составляет.

    Reply
  18. ershz

    Клиент telnet, который начиная с Vista, по умолчанию не устанавливается и требует включения через appwiz.cpl, в принципе не умеет работать с ком-портом.

    Вероятно, имелся в виду гипертерминал (HyperTerm), который тоже исключен из поставки.

    Putty — правильный выбор 🙂

    Reply
  19. monkbest

    Классно, я плюсанул, но в начале статьи обманул:

    получилось обойтись только usb модемом и платформой 1С

    Putty — часть платформы?

    Reply
  20. Sybr

    (20) Она была нужна, только для тестривания АТ команд. Можно было бы обойтись и без неё)

    Reply
  21. утюгчеловек

    Очень интересная статья. Поставил бы два плюса, если бы мог.

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

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

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

    для меня лично напомнило «путем нехитрых преобразований» в книгах Ландау по физике, где трехэтажный интеграл преобразуется в компактный одноэтажный. Нужно пояснение

    Reply
  22. Sybr

    (22) Да, тут конечно имеется модем с сим картой. Сначала необходимо установить драйвера для модема, обычно они на флэш памяти самого модема лежат и устанавливаются из автозапуска. В гипертерминале нужно выбрать этот установленный модем, нет сейчас его под рукой, не могу сказать как там точно это делать. Попробуйте скачать Путти, там сложностей никаких нет точно, выбирается только ком порт и скорость.

    Reply
  23. saiten

    Кстати, писать в ком-порт можно и стандартными средствами 1С:

     ком = новый ЗаписьТекста(«//./COM12»,КодировкаТекста.UTF16);
    ком.ЗаписатьСтроку(СтрокаДляЗаписиВПорт);
    

    Читать, наверное. тоже можно, но я не пробовал.

    Reply
  24. Sybr

    (24) У меня почему-то этот способ работал очень долго и постоянно зависал, изначально тоже так побывал, но остановился на варианте из статьи.

    Reply
  25. new_creation

    Спасибо за статью. Думаю скоро пригодится.

    Reply
  26. SoftLeon

    Спасибо за статью, очень актуально!!!

    Reply
  27. Sybr

    Пожалуйста)

    Reply
  28. new_creation

    Sybr, с помощью твоего кода пытаюсь получить смс-ки. При попытке считывании строк методом ReadLine Платформа виснет, не знаешь почему?

    Reply
  29. Sybr

    (29) new_creation, а в консоли попробовал подключиться к модему, происходит чтение? Скорее всего, если виснет, то никаких сообщений в данный момент с компорта нет.

    Reply
  30. new_creation

    (30) да. Смотрю через консоль — сообщения есть (3). Скажи, а ты настраивал модем ат-командами (например команда есть, чтоб он работал в режиме «только модем» и т.п.)? Это на сервере MS 2008… Как ты сделал, чтобы у тебя появилась строка Modem в Putty? У меня ее нет (Default…). Еще Putty портабельная, ничего? Еще возможно модем подключен через роутер (по сети настраиваю). Я в этих портах, роутерах не понимать особо. Подскажи, если знаешь… спасибо заранее.

    Reply
  31. Sybr

    (31) Модем не настраивал, работает «как есть». Строка Modem это просто название настроек у меня. У меня тоже была портабл версия. А на счет модема через роутер я не понял, это же USB модем, он у тебя в роутер воткнут? Если так, то странно, что Putty видит его. Подразумевается, что модем должен быть в USB, с эмуляцией com порта.

    Reply
  32. lunjio

    Решал подобную задачу, т.к имел опыт работы с мобильной платформой и веб-сервисами.

    В основной базе предоставил веб-сервис, который предоставляет не отправленные СМС из базы и конфигурацию на мобильной платформе, она использует веб-сервис, получает список смс к отправке, отправляет и фиксирует дату отправки, имеются настройки по периодичности отправки СМС, количеству, времени, лог работы. Единственная трудность при разворачивании, это поднятие веб-сервера для работы с вебсервисом и постоянное нахождение мобильного телефона дешевенького(выбор пал на ZTE за 5 тыс р.) в сети с предустановленной мобильной конфигурацией, запущенной, в сети. Если есть интересующиеся, могу сделать публикацию.

    Reply
  33. KeyFire

    У меня так и не получилось этим способом СМС-ки прочитать. Модем huawey M150-2. При использовании scripting.filesystemobject зависает. Терминалом если проверять те же команды, смс выводятся.

    Reply

Leave a Comment

Ваш адрес email не будет опубликован. Обязательные поля помечены *