Сравнение датчиков температуры DS18B20 и ДТВ-01-12 для электрокотлов «Эван»

В электрических котлах в качестве датчика температуры воздуха и температуры подачи/обратки наиболее распространены датчики на базе чипа DS18B20. Это широко распространенный датчик температуры с цифровым выходом 1-Wire. Достоинства DS18B20:

  • Выпускается различными производителями: Maxim Integrated, Dallas Semiconductor, Analog Devices, UMW и др.
  • Широко распространен, нет проблем с поставками. Производится в т.ч. китайскими производителями.
  • Есть различные корпуса как самого чипа так и законченных датчиков на его базе: нержавеющая гильза, пластиковые открытые и закрытые корпуса, корпус с резьбой для тройника, корпус под винт и пр.
  • Напряжение питания 3,3 — 5 В.
  • Диапазон измеряемых температур: −55…+125 °C.
  • Заявленная точность: ±0,5°C.
  • На одну шину (вывод микроконтроллера) можно повесить до 127 датчиков.

Недостатки DS18B20:

  • Значительный разброс измеренных значений в сравнении с поверенным эталоном.
  • При питании от 3,3 В стабильная работа датчика на кабеле ПВС 3×1,5 не превышает 12 м. На экранированной витой паре (CSS-FTP-4CU) с медными жилами — 30 м. На «витой паре» с омедненными жилами — до 25 м.
  • Разброс показаний температуры в сравнении с эталонным (поверенным) термометром составляет несколько °C. О точности ±0,5°C при реальных замерах речи не идет даже близко.
  • С ростом температуры (свыше 36 градусов) разница с поверенным датчиком по результатам тестов может составлять до 10 градусов в зависимости от экземпляра датчика.
  • При ошибке в полярности питания датчик выходит из строя.
  • Значительное количество подделок, которые непросто отличить от оригинального производителя.

Для снижения рисков некорректного замера температуры датчиками DS18B20 в электрокотлы «Эван» добавлена поддержка высокоточного токового (4..20 мА) датчика температуры воздуха ДТВ-01-12. Недостатки ДТВ-01-12:

  • Производится одним российским производителем, т.е. не столь распространен как DS18B20.
  • Более высокая сложность (датчик + электронная обвязка) по сравнению с DS18B20 (чип).
  • Доступен только в пластиковом корпусе IP40 для замера температуры воздуха в помещениях.
  • Для подключения каждого датчика нуден отдельный вывод на микроконтроллере, т.е. на один пин несколько датчиков не повесить.

Достоинства ДТВ-01-12:

  • Токовые датчики 4..20 мА — промышленный стандарт обеспечивающий высокую стабильность работы в условиях помех.
  • Стабильная работа датчика при длинах кабеля ПВС 3×1,5 свыше 35 м, на CSS-FTP-4CU — более 100 м.
  • При ошибке полярности питания датчик не выходит из строя. Есть встроенная защита.
  • Точность и стабильность замера температуры значительно выше, чем у DS18B20.
Рубрика: IT рецепты | Оставить комментарий

Выбеги насоса у электрических котлов. Какие риски и ограничения?

Довольно часто клиенты спрашивают про выбеги насоса у электрических котлов. Главным образом жалуются на их отсутствие в некоторых режимах. 🙂 Выбег — остановка насоса через некоторое время после отключения ТЭН-ов, когда циркуляция, вроде как, не нужна. Позволяет сэкономить немного электроэнергии. Мощность насоса порядка 80 Вт, на фоне потребления электрического котла, порядка 9 — 14 кВт (наиболее ходовые варианты) — экономия «на спичках», но все-же есть соблазн слегка сэкономить.

Рассмотрю подробно в каких случаях (режимах работы котла) выбеги насоса реализуются, а когда неудобства (ущерб) от отключения насоса потенциально превышает экономию на электроэнергии.

Режим поддержания температуры по воздуху

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

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

Основной риск включения выбегов (отключения насоса) в этом режиме, если датчики воздуха расположены слишком далеко от труб отопления и высоко (теплый воздух поднимается вверх), а теплоизоляция дома не очень хорошая. Гипотетически, теплоноситель в трубах уже может начать подмерзать, а датчик температуры воздуха может показывать ещё приемлемую температуру, если установлено какое-то низкое целевое значение.

Когда насос работает, т.е. есть циркуляция теплоносителя, то риск заморозить систему существенно снижается.

Режим поддержания температуры теплоносителя

При непрерывной работе насоса в режиме управления температурой по теплоносителю, алгоритм ПИД регулирования котла постоянно получает температуру теплоносителя. Теплоноситель гоняется по контуру и доносит до датчика температуры, расположенного, обычно, в колбе или на патрубке подачи/обратки, актуальную температуру из самых дальних уголков здания. Соответственно, риск, что в каком-то дальнем помещении, где может быть ещё и плохая теплоизоляция стен, температура опустится ниже 0 и система заморозится — минимальна.

На основании полученной ошибки алгоритм постоянно корректирует температуру теплоносителя, управляя ТЭН-ами, чтобы начинать заблаговременно нагревать теплоноситель, поддерживая установленную температуру (температура уставки) теплоносителя. При включенном насосе котел может поддерживать температуру теплоносителя близко к температуре уставки.

Если насос остановить, то датчик температуры теплоносителя будет показывать только температуру в теплоизолированной колбе или на патрубке. Температура в колбе при отключенном насосе при отстутствии протока может опускаться довольно медленно. Соответственно, алгоритм ПИД регулирования будет получать показатели температуры не из системы отопления (радиаторов)? поэтому качественно отрабатывать поддержание установленной температуры не будет. Грубо говоря в системе отопления вода уже замерзла, а в колбе все ещё нормальная температура. Информация о температуре теплоносителя ложная, поскольку нет циркуляции.

Чтобы регулярно актуализировать данные по температуре теплоносителя нужно:

  1. Периодически включать насос.
  2. Прогонять теплоноситель по контуру. Сколько времени прогонять зависит от длины системы отопления.
  3. Замерять актуальную температуру теплоносителя. В идеале должно пройти несколько циклов.
  4. Получив температуру из самых дальних уголков здания лихорадочно включать ТЭН-ы, пытаясь скорректировать уход температуры от целевой.

Например, включаем насос каждые 2 часа, чтобы актуализировать температуру теплоносителя. В течении этих двух часов алгоритм ПИД регулирования не получает актуальную температуруот системы отопления, а руководствуется локальными датчиками температуры в колбе или на патрубке приточки/обратки. Не получая объективную информацию он управляет температурой теплоносителя абы как. В результате получаем противоречие:

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

В результате график температуры теплоносителя вместо плавного и максимально близкого к температуре уставки будет резко меняться, что в значительной степени скажется на комфорте в помещении. Точного регулирования температуры уже не будет. Поэтому адекватные производители электрических котлов не реализуют выбеги насосов в режиме управления по температуре теплоносителя, чтобы избежать вопросов клиентов почему при срабатывании выбегов температура в помещении «скачет».

Нормальное поддержание целевой температуры в режиме теплоносителя возможно только когда есть постоянная циркуляция и датчик температуры обратки/подачи постоянно отслеживает актуальную температуру теплоносителя в системе. Соответственно, при отключении циркуляции даже на короткое время при работе в режиме по теплоносителю приведет к плохому поддержанию температуры в помещении.

Выбеги (или их аналог для экономии электроэнергии) в этом режиме можно использовать в двух случаях:

  • На радиаторах в здании стоят датчики температуры, чтобы обеспечить актуальными данными о температуре теплоносителя алгоритм котла. Маловероятно, что клиенты готовы тащить такое количество проводов или ставить радиодатчики на каждый радиатор, чтобы заработали выбеги и при этом не ухудшилось качество поддержания целевой температуры в помещении.
  • В котле используется насос с электронным управлением, например, с помощью ШИМ, т.е. когда электроника может снизить скорость работы насоса до минимальной, не отключая совсем. Пу сути, когда используется насос с ШИМ, то «выбеги» (полное отключение насоса) не используются, но электричество экономится. Алгоритм получает актуальную информацию из системы отопления и может своевременно изменить скорость (энергопотребление насоса), чтобы поддерживать температуру на заданном уровне. Но такой насос стоит существенно дороже обычного и тарифы на электроэнергию в России вряд ли позволят быстро окупить такие инвестиции.

Отмечу также, что режим работы насоса, когда циркуляция полностью останавливается (насос отключается), а затем, после полной остановки движения теплоносителя, возобновляется снова — неблагоприятен для насоса. Чаще всего выход из строя электрических/электронных устройств происходит в цикле включения/выключения. В начальные моменты токи в обмотке насоса значительны. Когда насос постоянно в работе — ему нужно только поддерживать циркуляцию и это более щадящий режим с меньшим энергопотреблением.

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

Также и с насосом, в момент пуска нагрузка на насос максимальна. После начала движения теплоносителя нагрузка на насос снижается. Поэтому частое включение и отключение насоса приводит к повышенному механическому износу и снижает его ресурс.

Прикинем стоимость электроэнергии в год:

  • Насос работает 24 часа в сутки.
  • Отопительный сезон примерно 6 месяцев.
  • Среднее количество дней в месяце — 30.
  • Энергопотребление 80 Вт или 0,08 кВт.
  • Стоимость одного кВт примерно 4 руб.

Итого получаем: 0,08 кВт * 24 часа * 30 дней * 6 мес * 4 руб = 1382 руб. в год. Вопрос, «стоит ли овчинка выделки»?

При этом при частых отключениях насоса увеличивается вероятность выхода из строя, т.е. есть риск, что насос выйдет из строя до гарантии. При этом производитель, помимо затрат на сам насос, понесет расходы на выезд сервисного инженера. Я не знаю компаний производящих качественные электрические котлы, которые шли бы на подобный риск выхода из строя ключевого и весьма недешевого компонента.

Включение выбега эквивалентно ситуации, когда автомобиль едет по трассе и для экономии топлива периодически останаливается полностью, а затем стартует вновь. По-сути, напоминает перемещение по городу в «пробках». В «пробках» снижения расхода топлива не замечено и износ компонентов выше, чем при равномерной работе на 3/4 передаче.

В плане экономии электроэнергии в режиме по теплоносителю хороший вариант когда котел управляет насосом с частотным управлением (например, через ШИМ). В этом случае его не нужно останавливать. По аналогии с авто можно скинуть скорость на 2-ю передачу и ехать медленно, но когда надо, не столь энергозатратно и разрушительно для компонентов переключится на 3/4 передачу. В случае с насосом можно уменьшить обороты до минимума, но не отключать. Когда же теплоноситель начнет остывать из-за теплопотерь здания, добавить оборотов. Но такой насос стоит в несколько раз дороже обычного, поэтому электрические котлы с таким насосом стоят дорого и мало кто готов за них переплачивать. Очень долго придется «отбивать» стоимость за счет сэкономленной электроэнергии в России.  

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

Использовать выбеги в режиме управления по теплоносителю нецелесообразно.

Хотя режим «Антизамерзания» является частным случаем управления по температуре теплоносителя, но в этом режиме нет требований к точности поддержания целевой температуры. Т.е. какие там флуктуации температур будут в помещении — все равно, поскольку основная задача обеспечить температуру теплоносителя не ниже заданных, например 8 град. С. Собственно, поэтому можно отключить насос на сутки и включать раз в сутки, чтобы прогнать теплоноситель и замерить его актуальную температуру.  За сутки хорошо утепленное здание при не очень низкой температуре на улице остынет незначительно. Хотя, есть риски, что при плохой теплоизоляции и на улице -40, система может разморозится. 

Управление температурой по уличному термодатчику (метеосерверу) 

Режим управления по кривым погодозависимой автоматики (ПЗА) — это частный случай управления по теплоносителю. Котел считывает температуру на улице, по графикам вычисляет температуру уставки для теплоносителя и пытается удерживать её в системе отопления. Соответственно, если отключить насос, то получим ситуацию подробно описанную выше. Ни о какой плавности и точности поддержания температуры не может быть и речи. Алгоритм ПИД регулирования не будет нормально отрабатывать. Соответственно, в этом режиме выбеги использовать нельзя.

Управление по OpenTherm внешним контроллером

Когда к котлу цепляется внешний контроллер — это не означает, что котел снимает с себя всякую ответственность за результат и полностью переходит под внешнее управление. Котел обеспечивает минимально необходимые для безопасной работы системы отопления алгоритмы. Например, он контролирует, чтобы система не разморозилась. Задания на управление температурой теплоносителя при этом приходят от внешнего контроллера.

В протоколе OpenTherm нет функций, которые позволяли бы управлять насосом котла внешнему контроллеру. Даже если бы и был, разработчики котлов не могут быть уверены на 100%, что все производители GSM контроллеров его корректно реализовали. Работа насоса — это важный момент обеспечения безопасности работы котла.

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

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

Котел не сможет поддерживать температуру теплоносителя затребованную контроллером. Соответственно, начнутся проблемы со сходимостью алгоритма контроллера. Он будет отдавать команду на уставку температуры котлу, считая, что тот достаточно сообразителен, чтобы поддерживать температуру уставки, а котел будет его регулярно разочаровывать. 🙂 В результате, мягко говоря, температура будет поддерживаться очень неточно.   

Если внешний контроллер работает в режиме управления по воздуху, то, казалось-бы, рисков разморозить систему нет. Например, при использовании штатной автоматики котла при работе по воздуху, выбеги безопасно отрабатывают.

Проблема в том, что по шине OpenTherm контроллер не может передать котлу в каком режиме он работает: управление по воздуху или по теплоносителю. В OpenTherm нет такой команды.

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

При этом контроллер будет думать, что температура теплоносителя, получаемая от котла по шине OpenTherm — актуальная. Соответственно, алгоритм работы контроллера при управлении по температуре теплоносителя перестанет корректно отрабатыват из-за ложных данных.

Опять приходим к тому, что только в котлах с управляемой скоростью насоса (например по ШИМ) можно гарантированно обеспечить безопасную работу котла при управлении по OpenTherm, при этом максимально снизив потребление электроэнергии.

Возможен не особо надежный компромиссный вариант. При подключении внешнего контроллера к котлу нужно обязательно требовать подключить к нему датчик температуры воздуха. Он будет использоваться котлом для контроля температуры в помещении, чтобы не разморозить систему если контроллер дает неверные уставки или отказал. Если датчик температуры воздуха вышел из строя, котел должен запретить все выбеги и включить насос на постоянную работу. Соответственно, максимальный ущерб, который возможен при отказе контроллера — живность в доме может замерзнуть.

Котел должен знать, что контроллер при этом находится в режиме управления по воздуху. Как уже упомянул выше, контроллер не имеет технической возможности передать котлу эту информацию по шине OpenTherm. Единственный способ — в настройках котла пользователю в явном виде указать, что внешний контроллер работает по температуре воздуха в помещении.

Эта настройка должна задаваться каждый раз при выборе внешнего управления OpenTherm и сбрасываться при переходе в любой другой режим управления. Осознанная установка пользователем с пониманием возможных последствий. Но, по опыту, они далеко не всегда осознают к чему могут привести неправильные настройки.

При этом есть риск роста сервисных заявок. Пользователь может сменить режим на контроллере с управления по воздуху на теплоноситель/уличный, а на котле забыть сменить режим работы контроллера.

После этих установок котел будет считать, что контроллер управляет им, замеряя температуру воздуха и показания температуры теплоносителя ему не нужны для корректной отработки алгоритма. Тогда выбеги будут отрабатывать как и в случае, когда на самом котле выбран режим по воздуху.

Рубрика: IT рецепты | Оставить комментарий

Проработка умного IVR с распознаванием речи сервисной службы

При разработке IVR с распознаванием речи для решения задач сервисной службы нужно учитывать ряд моментов. Я разрабатывал IVR на платформе Aimylogic, но логика приемлема для любых других.

  1. Когда человек слышит голосового ассистента, даже если тот представляется как бот-оператор, он не сразу понимает, что разговаривает с роботом.
  2. Даже если заготавливать список вопросов, человек, не поняв, что говорит с ботом хочет использовать свои вопросы.
  3. Очевидно, что те, кто звонит, надеются сразу пообщаться с человеком, но это, к сожалению, нынче очень дорого и, зачастую, нереально. Например, при сезонном характере продаж потребность в сервисе может менятся ов очень значительных пределах.
  4. Интеграция с CRM системой (service-desk) должна предполагать, что человек услышав бота положит трубку. Хотя проблема у него осталась. Для дальнейшей проработки IVR нужно фиксировать факт звонка в момент его совершения. Даже если клиент решил закончить разговор сразу.
  5. При распознавании бот ошибается, когда слово отсутствует в словарях, либо близко по звучанию с словами из словаря. Например, у нас в линейке производимой продукции есть два названия на английском: Stout и MyHeat. Это боль для системы распознавания. Она слышит совершенно по-разному и часто ошибается при распознавании этих слов.
  6. Для анализа фраз клиента нужно сохранять всю фразу распознанную ботом, чтобы сотруднику техподдержки не пришлось прослушивать аудиофайл. Это занимает гораздо больше времени, нежели прочитать стенограммму.
  7. Человек услышав бота, особенно если тот говорит не в попад, может выругаться. Целесообразно распознавать нецензурную лексику (в AimyLogic это зашито) и выдавать снимающее напряжение фразу.

Следуя вышеперечисленному примерная логика построения IVR следующая:

  1. Бот выдает приветственную фразу, представляясь, что он бот. Это позволит понять человеку, что он разговаривает с программой, которая не может вести диалог свободно. Подобные технологии уже есть для текстов, например, ChatGPT, но пока что я не видел нормального встраивания в системы умного (smart) IVR присутствующего на рынке России.
  2. Можно поставить блок расписание, чтобы исключить запись звонков в выходные. Инженеры не могут помочь в выходные, а до понедельника пользователь уже сможет почитать инструкцию и с высокой вероятностью решит сам. 🙂
  3. Некоторые нетерпеливые пользователи могут звонить повторно, если с ним не связались в течении нескольких часов. В этом случае имеет смысл смысл по номеру телефона взять номер заявки и сообщить этот номер. И узнать, у человека возникла новая проблема или он звонит по старой.
  4. Если позвонивший не бросил сразу трубку, значит стоит записать его контакт (номер телефона) в CRM (ServiceDesk), на случай если дальше произойдет обрыв соединения, либо клиент испугается (посчитает бесполезным) общение с ботом. Т.е. сервисная заявка должна создаваться ДО того как бот задаст клиенту вопросы. Хотя вопрос спорный.
  5. Создание сервисной заявки в самом начале диалога позволит в дальнейшем проанализировать процент людей, которые потенциально не готовы общаться с ботом. Это важно для развития системы.
  6. Далее бот начинает задавать наводящие вопросы для классификации проблемы, которая возникла у клиента. По мере получения ответов на вопросы бот добавляет в созданную сервисную заявку информацию. При таком подходе даже если у клиента пропала связь (звонки чаще всего с мобильного) у нас уже сохранен номер его телефона и можно перезвонить.
  7. В интентах (типовых шаблонах для распознавания ответов) невозможно предусматреть все типовые ответы клиента, поэтому при ответе («любая другая фраза») она должна сохранятся как есть и уведомление о том, что человек ответил на вопрос нестандартно (не как мы предполагали) должно отправляться по e-mail разработчикам бота.
  8. Нельзя в синтезе речи использовать только вопросительную фразу, поскольку бот интонационно не всегда передает вопросительный характер предложения. В обязательном порядке нужно после основной вопросительной фразы задать короткий уточняющий вопрос: «Верно?», «Правильно?», «Корректно?», «Правильно ли я поняла?» и т.д. На такие вопросы позвонивший, как правило, дает вполне типовой ответ, который хорошо распознается штатным интентом «Согласие» в AimyLogic.
  9. Дата (например, дата производства оборудования) плохо распознается ботом, поэтому нужно сохранять исходную фразу $queryText.
  10. Номера телефона распознается хорошо, однако клиент может пожелать, чтобы ему перезвонили на другой номер телефона. Стандартный интент по распознаванию номера телефона в AimyLogic работает дорстаточно надежно. При зачитывании номера для проверки нужно использовать регулярное выражение из моей предыдущей статьи, чтобы разбить номер телефона на блоки цифр по 3. Так удобнее воспринимать на слух.
  11. В конце разговора, перед тем как бот положит трубку, нужно передать в CRM в качестве стенограммы полную историю общения взятую из переменной $chathistory. Это позволит сервисному инженеру быстро пробежаться по вопросу клиента, не тратя время на прослушивание аудиозаписи.
Рубрика: IT рецепты | Метки: | Оставить комментарий

Передача данных из AimyLogic для создания записи смарт-процесса в Битрикс (REST API)

В предыдущей статье я подробно рассмотрел создание лида в Bitrix с передачей необходимых параметров из AimyLogic. В этой статье рассмотрим как создать новый элемент (запись) для ранее созданного смарт-процесса. Создание смарт-процесса подробно рассмотрено в документации Битрикс: https://helpdesk.bitrix24.ru/open/13315798/ Останавливаться на этом не буду.

Я создал смарт-процесс с названием «Сервисная заявка». В неё из AimyLogic должны попадать заявки на сервисную поддержку для отработки инженерами сервисной службы.

Создание записи простого смарт-процесса через REST API

Создадим запись смарт-процесса в Битриксе через REST API. Запись смарт-процесса создается при вызове https://dev.1c-bitrix.ru/rest_help/crm/dynamic/methodscrmitem/crm_item_add.php

Ключевой параметр в аргументах crm.item.add — entityTypeId, т.е. идентификатор смарт-процесса. Чтобы найти этот параметр для созданного смарт-процесса переходим в CRM -> Ещё -> Настройки -> Список смарт-процессов:

В списке смарт-процессов первая колонка — идентификатор типа смарт-процесса. Это и есть искомый entityTypeId.

Сделаем простой тестовый запрос для отправки через Postman:

{
  "entityTypeId": "158",
  "fields": {
       "TITLE": "ИП Титов"
   }
}

При отправке запроса не забываем включать Headers и добавлять строчку:

Content-Type: application/json

иначе параметры из JSON не «лягут» в Битрикс.

После выполнения запроса в результатах получим следующий JSON:

 {
    "result": {
        "item": {
            "id": 2,
            "xmlId": null,
            "title": "ИП Титов",
            "createdBy": 177,
            "updatedBy": 177,
            "movedBy": 177,
            "createdTime": "2023-03-31T11:16:32+03:00",
            "updatedTime": "2023-03-31T11:16:32+03:00",
            "movedTime": "2023-03-31T11:16:32+03:00",
            "categoryId": 5,
            "opened": "N",
            "stageId": "DT158_5:NEW",
            "previousStageId": "",
            "begindate": "2023-03-31T03:00:00+03:00",
            "closedate": "2023-04-07T03:00:00+03:00",
            "companyId": null,
            "contactId": null,
            "opportunity": 0,
            "isManualOpportunity": "N",
            "taxValue": 0,
            "currencyId": "RUB",
            "opportunityAccount": 0,
            "taxValueAccount": 0,
            "accountCurrencyId": "RUB",
            "mycompanyId": null,
            "sourceId": "CALL",
            "sourceDescription": null,
            "webformId": null,
            "assignedById": 177,
            "observers": [],
            "contactIds": [],
            "utmSource": null,
            "utmMedium": null,
            "utmCampaign": null,
            "utmContent": null,
            "utmTerm": null,
            "entityTypeId": 158
        }
    }
}

В результирующем JSON фигурируют все поля созданного смарт-процесса.

Пользовательские поля в смарт-процессах

Добавим в созданный смарт-процесс несколько новых полей:

Для обработки сервисными инженерами голосовой бот должен получить от клиента следующую информацию:

  • модель оборудования по которому возник вопрос,
  • регион откуда звонит клиент (от этого зависит, например, где находятся ближайшие сервисцентры).
  • описание проблемы (вопрос),
  • если клиент считает, что оборудование на гарантии — дату производства с стикера на котле,
  • имя клиента,
  • номера телефона для связи.

Для примера создадим поле «Регион»:

Повторюсь, что после создания элемента смарт-процесса возвращается JSON со списком всех полей смарт-процесса с их значениями. Например, после добавления пары полей в JSON появляются записи:

...
"ufCrm3_1680254883": "",
"ufCrm3_1680255422": "",  
...

Обратщаю внимание на тот момент, что в интерфейсе Битрикса название поля «UF_CRM_3_1680254883«, а в JSON, который возвращается от Битрикса это поле называется «ufCrm3_1680254883«. Соответственно, для отправки через REST API нужно использовать имя, которое возвращается в JSON при добавлении элемента смарт-процесса. Не знаю, зачем сделали такое различие в именах, вносящее путаницу.

{
  "entityTypeId": "158",
  "fields": {
    "SOURCE_ID": "14",
    "contactId": "10060",
    "ufCrm3_1680255422": "EvanExpert", 
    "ufCrm3_1680254883": "Москва",
    "ufCrm3_1680261235": "Проблема пользователя",
    "ufCrm3_1680261458": "16.10.2022"
   }
}

При выполнении запроса возвращается JSON следующего вида:

{"item":{"id":151,"xmlId":null,"title":"Сервисная заявка #151","createdBy":177,"updatedBy":177,"movedBy":177,"createdTime":"2023-05-26T16:08:58+03:00","updatedTime":"2023-05-26T16:08:58+03:00","movedTime":"2023-05-26T16:08:58+03:00","categoryId":5,"opened":"N","stageId":"DT1585:NEW","previousStageId":"","begindate":"2023-05-26T03:00:00+03:00","closedate":"2023-06-02T03:00:00+03:00","companyId":null,"contactId":11599,"opportunity":0,"isManualOpportunity":"N","taxValue":0,"currencyId":"RUB","opportunityAccount":0,"taxValueAccount":0,"accountCurrencyId":"RUB","mycompanyId":null,"sourceId":"14","sourceDescription":null,"webformId":null,"ufCrm31680254883":"Великий Новгород","ufCrm31680255422":"ExpertPlus","ufCrm31680261235":"Тест","ufCrm31680261458":"01.01.1900","ufCrm31682360216":"","ufCrm3_1682682092":null,"assignedById":177,"observers":[],"contactIds": 11599,"utmSource":null,"utmMedium":null,"utmCampaign":null,"utmContent":null,"utmTerm":null,"entityTypeId":158}}

Например, чтобы получить номер заявки надо при возврате:

$ticket = $httpResponse.result;
$ticket_id = $ticket.item.id;

В переменной $ticket_id содержится номер только что созданной сервисной заявки.

Добавление контакта через REST API

Для добавления контакта используется метод Битрикса crm.contact.add. JSON для REST API выглядит так:

{
"fields":
{ 
"NAME": "Андрей", 
"SECOND_NAME": "Алексеевич", 
"LAST_NAME": "Федоров", 
"TYPE_ID": "CLIENT",
"SOURCE_ID": "SELF", 
"OPENED": "Y",  
"PHONE": [{"VALUE": "+79XXXXXXXXX", "VALUE_TYPE": "MOBILE"}, {"VALUE": "+79YYYYYYYYY", "VALUE_TYPE": "HOME"}]
}
}

В Postman этот запрос:

После отправки запроса получаем результат, где в поле result содержится ID созданной записи:

{
    "result": 12062
}

При повторном звонке клиента нужно по номеру телефона найти контакт в Битриксе. Фильтрация описанная здесь не отрабатывает на номерах телефонов. Точное значение ищется, а вот маски или номера, когда в одном случае номер начинается с +7, а в другом с 8 — не находятся.

Единственный рабочий метод, который нормально находит идентификаторы клиента по номеру телефона, оказался вот этот: https://dev.1c-bitrix.ru/rest_help/crm/auxiliary/duplicates/crm_duplicate_findbycomm.php

JSON запрос выглядит следующим образом:

{
   "entity_type": "CONTACT",
   "type": "PHONE",
   "values": [ "+7960XXXXXXX", "8906XXXXXXX"]
}

Поиск этим методом проходит по полному номеру телефона, т.е. номер должен начинатся для России с +7 или 7 или 8 и дальше 10 цифр номера телефона. Маски задавать нельзя.

Однако, этот поиск находит все варианты записи телефона, даже если при сохранении номера начинались с +7 или 8 или были указаны разделители в виде «-«. Результат возвращается в виде массива с ID из контактов:

 {
    "result": {
        "CONTACT": [
            11599,
            11600,
            12062,
            12063,
            12064
        ]
    }
}

Возвращаются все контакты у которых встречается этот номер телефона. В AimyLogic JSON на получение контакта такой-же, как вышеприведенный. Результат $httpResponse.result сохраняется в переменную $contacts. На ветвление с успешной отработкой HTTP запроса нужно прописать короткий JavaScript:

if ($contacts.hasOwnProperty("CONTACT")) { 
    if ($contacts.CONTACT.length > 0) {
        $contact_id = $contacts.CONTACT[0]
    }
} else {
    $contact_id = null;
}

Производится проверка, что в переменной $contacts присутствует свойство «CONTACT», после чего проверяется, что размер массива содержит хотя-бы один элемент и этот единственный ID контакта перемещается в переменную $contact_id. Найденное значение используется при создании нового контакта.

В Aimylogic:

  1. Выполняется JSON для проверки есть ли клиент с заданным номером телефона.
  2. В блоке «Условие» производится проверка, если $contact_id == null, тогда выполняется блок «HTTP запрос» для создания нового клиента. В RESPONSE $client_id = $httpResponse.result.
  3. Если $contact_id !== null, то клиент уже есть в Битриксе и в запросе на создание элемента смарт-процесса используется полученный при выполнении запроса $contact_id.
{
  "entityTypeId": "158",
  "fields": {
    "SOURCE_ID": "14",
    "contactId": "$contact_id",
    "ufCrm3_1680255422": "$equipment", 
    "ufCrm3_1680254883": "$client_city",
    "ufCrm3_1680261235": "$question",
    "ufCrm3_1680261458": "$productiondate"
   }
}

Добавление в смарт-процесса Битрикс поля с типом «Список»

Чтобы добавить в созданный смарт-процесс Bitrix поля с типом «Список» нужно найти ID элементов из списка. В интерфейсе Bitrix это сделать не получилось, поэтому нужно вызвать метод crm.item.fields.json, передав в параметре id смарт-процесса.

В POST запросе в Postman URL для теста выглядит как-то так: https://xxxxx.ru/rest/yyy/zzzzzzzzz/crm.item.fields.json

В headers:

Content-Type: application/json

Body:

{
"entityTypeId": "158"
}

Ну и в result получаем JSON со списком всех полей смарт-процесса:

"ufCrm3_1697115862": {
                "type": "enumeration",
                "isRequired": false,
                "isReadOnly": false,
                "isImmutable": false,
                "isMultiple": false,
                "isDynamic": true,
                "items": [
                    {
                        "ID": "59",
                        "VALUE": "Другое."
                    },
                    {
                        "ID": "55",
                        "VALUE": "Котел не греет. Сломался. "
                    }
                ],
                "title": "Важность",
                "listLabel": "",
                "formLabel": "Важность",
                "filterLabel": "",
                "settings": {
                    "DISPLAY": "LIST",
                    "LIST_HEIGHT": 1,
                    "CAPTION_NO_VALUE": "",
                    "SHOW_NO_VALUE": "Y"
                },
                "upperName": "UF_CRM_3_1697115862"
            },

Добавляем это поле в JSON:

{
  "entityTypeId": "158",
  "fields": {
    "SOURCE_ID": "14",
    "contactId": "$contact_id",
    "ufCrm3_1680255422": "$equipment", 
    "ufCrm3_1680254883": "$client_city",
    "ufCrm3_1680261235": "$question",
    "ufCrm3_1680261458": "$productiondate",
    "ufCrm3_1697115862": "59"
   }
}

Смарт процесс успешно создается и значение поля типа «Список» устанвливается с id = 59, т.е. «Другое».

Рубрика: IT рецепты | Оставить комментарий

Отработка нестандартных фраз клиентов в Aimylogic

При разработке интентов для голосового IVR (Умный IVR) AimyLogic непросто предусмотреть все возможные варианты ответов пользователей на заданный вопрос. Нужно оперативно получать информацию о фразах, которые не распознались имеющимися интентами, чтобы оперативно добавлять в сценарий.

Предположим, в блоке «Синтез речи» мы создали несколько интентов для распознавания типов продукции по которым обращается клиент. При этом не учли, что пользователь, на вопрос «С каким оборудованием у вас возникла проблема?» назовет оборудование как-то экзотически. Например, вместо «MyHeat» — «Май Хер» (не шутка 🙂 ). Нужно отлавливать такие нестандартные варианты.

В блоке «Синтез речи» при добавлении «Сделать свой интент» в качестве варианта ветвления есть вариант «Любая другая фраза». В эту ветку попадают фразы, которые не были распознаны другими интентами. Соответственно, чтобы оперативно получать информацию о нестандартных фразах проще всего повесить на эту ветку отправку сообщения в почту.

Добавим блок «Отправка e-mail». Он немного ушербный, т.к. позволяет добавить только одного получателя сообщения. Соотвественно, придется на почтовом сервере заводить группу рассылки, чтобы отправлять почту всем инженерам, сопровождающим AimyLogic.

Другой вариант — использовать для отправки сообщений вебхук внешнего сервиса IFTTT: https://help.aimylogic.com/docs/ru/publication_channels/ifttt/ifttt_email. Но это дополгнительная точка отказа, поэтому лучше сделать штатными средствами AimyLogic:

В тексте сообщения, чтобы отправить нераспознанный интентами текст используется переменная $queryText. Также для быстрого нахождения записи разговоров в «Диалоги» стоит вставить в текст переменную $rawRequest.caller в которой содержится номер телефона позвонившего.

После того, как я в тесте написал «Передавай», успешно отправился e-mail и пришло вот такое сообщение:

Рубрика: IT рецепты | Метки: | Оставить комментарий

Пользовательские сущности (справочники) в Aimylogic

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

https://help.aimylogic.com/docs/ru/how-to-create-a-script/user-says/template_syntax/

Итак, мне нужно решить следующую задачу:

  1. Компания производит ряд продуктов.
  2. Голосовой бот задает вопрос клиенту с каким продуктом проблема.
  3. Клиент отвечает на вопрос и во фразе должен фигурировать один из продуктов.
  4. Необходимо минимизировать количество интентов, чтобы обработка была максимально компактной и более красивой.
  5. После определения продукта должно отработать ветвление в зависимости от типа продукта.

Самый простой вариант реализации — это в блоке «Синтез речи» добавить интенты по каждому типу продукта. И дальше сделать ветвления.

Реализуем тоже самое с помощью пользовательских сущностей. Зайдем в «Сущности» -> «Создать справочник синонимов»:

Создаем справочник сущностей с именем $products. Для примера три сущности:

В синонимах не отрабатывают шаблоны, т.е. если задать «Эксперт * Плюс», то фраза «Эксперт !!! Плюс» подходящая под шаблон распознана не будет. Например, если пользователь в текстовом чате может написать «МайХит» вместе и «Май Хит» раздельно, то придется в синонимах указывать оба значения.

При появлении во фразе пользователя заданного для сущности синонима в переменной $products появится имя сущности. Его можно проверить в блоке «Условие», например, с помощью выражения $products == «Expert Plus».

Реализуем простой функционал заполнения переменной $products для теста, чтобы лучше понять как работают сущности:

  1. В блоке «Синтез речи» спрашиваем клиента «С каким продуктом у вас проблема?».
  2. В интент вставляем потенциальный ответ пользователя, но вместо конкретного названия продукта используем сущность $products. Например, если в интенте будет фраза: * [проблема] * с $products, то интент сработает только если клиент скажет, например «У меня проблема с Эксперт Плюс», либо кратко ответит «с Эксперт Плюс». Но если клиент ответит «Эксперт Плюс», то синоним не распознается, поскольку наличие «с» перед «Эксперт Плюс» обязательное.
  3. С обработанного интента переходим на блок «Синтез речи», где выводим значение переменной $products, чтобы убедится, что оно заполнено верно.

Результат работы:

Тестируем как отрабатывает ветвление:

Если нам все-же нужно использовать шаблон, то тогда можно усложнить интент, записав его, например, таким образом:

$products::first * $products::second *

В этом случае сначала будет выделена первая часть, которая попадет в переменную $first и вторая часть, которая отправиться в $second.

Например, добавим сущность Plus:

Если пользователь во фразе выругается :-), например: «Эксперт, блин, плюс», то интент:

$products::first * $products::second *

отработает эту фразу и в переменная $first = «Expert», а $second = «Plus». Это не удобно, но как вариант…

В некоторых случаях нужно в одной фразе определить producttype (котел, бойлер косвенного нагрева, GSM контроллер и пр.) и модель. Например, пользователь может в одном предложении смешать тип оборудования и продкт: «котел Эван Эксперт», «котел стаут плюс» и т.п.

При этом работает вариант с использованием двух разных сущностей в одном интенте:

* $products::product * $producttype::type *

Чтобы перебрать все возможные комбинации достаточно задать следующие интенты:

Отрабатывает также запись интентов без переноса результата в переменные:

При этом последовательнось задания интентов не влияет на результат. Можно последние две строчки поместить в начало, отрабатывает также.

Все бы ничего, но в ряде случаев вторая переменная не обнуляется. Например, если ответить «котел», то в $products остается значение от предыдущего обращения. Поэтому более корректный вариант — инициализировать переменные перед вызовом интента.

$product = "";
$type = "";

И далее добавить блок в котором задается значение переменной $type для случая когда пользователь назвал модель оборудования, но во фразе не был указан тип:

switch ($product) {
  case "Expert":
  case "ExpertPlus":
  case "Practic":
  case "PracticPlus":
  case "Stout":
  case "StoutPlus":
  case "Next":
  case "NextPlus":
  case "Start":
  case "StartPlus":
    $type = "WaterHeater";
    break;    
}

При этом если пользователь во фразе про оборудование назовет «котел», то переменная $product будет пустой и алгоритм начнет задавать уточняющие вопросы для конкретизации модели.

Если в сценарии задана некоторая уточняющая логика, например, пользователь назвал продукт «Эксперт», но есть расширенная модификация «Эксперт Плюс», он идет с WiFi. Стоит задать пользователю уточняющий вопрос: «Котел с WiFi?». Если тот отвечает утвердительно, то нужно откорректировать выбор пользователя, заменив значение переменной $product с «Expert» на «ExpertPlus». Итак, при ветвлении с утвердительного ответа на вопрос про WiFi идет ветка на блок «Код» в котором стоит следующий JavaScript:

switch ($product) {
  case "Expert":
    $product = "ExpertPlus";
    break;
  case "Practic":
    $product = "PracticPlus";
    break;
  case "Stout":
    $product = "StoutPlus";
    break;
}

Рубрика: IT рецепты | Оставить комментарий

Интеграция AimyLogic с SIP АТС Asterisk

для приема звонков с офисной АТС Asterisk на сайте AimyLogic есть инструкция, но по ней настроить не удалось. Вот пример настроек авторизации из статьи:

1. Перейдите в Aimylogic.
2. Откройте Профиль → Настройка телефонии → Создать подключение.
3. В поле Логин укажите match_trusted_ip_port, поле Пароль оставьте пустым.
4. В поле Хост/IP укажите внешний IP адрес вашей SIP ATC, а в поле Порт — соответствующий вашим настройкам порт.
5. Активируйте переключатель Принимать входящие звонки.
6. В разделе Расширенные настройки отключите параметр Требуется регистрация.

В таком варианте не работает. Отработало так:

  1. Перейдите в Aimylogic.
  2. Откройте Профиль → Настройка телефонии → Создать подключение.
  3. В поле Логин укажите внутренний номер абонента на Asterisk ,
  4. В поле Пароль прописать авторизацию для указанного SIP номера.
  5. В поле Хост/IP указать внешний IP адрес Asterisk. Мы указывали именно IP, но доменное имя наверняка тоже сработает.
  6. В поле Порт — проброшенный порт на Asterisk.
  7. Активировать переключатель Принимать входящие звонки.
  8. Визуально В разделе Расширенные настройки ВКЛЮЧИТЬ параметр Требуется регистрация.
  9. Прописать на firewall разрешение на звонки с IP адреса: 82.202.218.130.
  10. На Asteriske ограничить исходящие звонки для этого SIP номера только внутренними.
  11. После того как создано соединение в настройках Aimylogic на SIP аккаунт Asterisk, в логах данные о коннекте отображаются не сразу, а спустя порядка 45 сек. Об этом не написано в доке Aimylogic, но при отладке важно.

Перевод звонка из AimyLogic на оператора Asterisk

В сценариях AimyLogic есть блок «Перевод звонка на оператора». В нем указывается просто внутренний номер абонента или группы абонентов на Asterisk. Звонок нормально отрабатывает переход.

Для этого блока есть два варианта ветвления:

  • Перевод состоялся — отрабатывает сразу после того как после успешного соединения завершен разговор (положили трубку). Т.е. в сценарии после общения с оператором можно продолжить логику отработки сценария.
  • Перевод не состоялся — отрабатывает, если не сработал перевод на оператора и можно реализовать какую-то бизнес-логику, вроде фиксации номера звонка в качестве лида в Битриксе.
Рубрика: IT рецепты | Метки: | Оставить комментарий