Руководство для непродвинутого пользователя по Mijia Automation Geek Edition или китайский язык это не страшно

в 9:23, , рубрики: Mijia Automation Geek Edition, Умный дом Xiaomi

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

Когда стандартных возможностей Mi Home больше не хватает

Создание типового сценария автоматизации для умного дома экосистемы Xiaomi в приложении Mi Home в общем не сильно отличается от создания сценариев в других экосистемах и состоит из типовых блоков: «триггер/событие», «условия выполнения» и «выполнение действия».

Все лаконично, просто, понятно и удобно, но эта простота содержит в себе ряд ограничений – что делать если блок действий сложный, содержит внутри себя условия выполнения и ветвления и активатором действий вообще могут выступать несколько различных триггеров? Я первый раз столкнулся с ограничениями Mi Home при подключении умного термостата HeatCold TH123, оказалось, что в нем некорректно реализован аппаратный триггер и вместо создания событий при изменении температуры он просто несколько раз в секунду порождал поток событий, с которыми невозможно было работать. Одним из вариантов решения задачи, был бы опрос состояния датчиков в цикле, но, как оказалось в стандартных сценариях Mi Home нет цикла, а создание набора однотипных таймеров выглядело бы некрасиво и было бы трудно сопровождаемым решением. К тому же, владельцы китайских устройств, привязанных к китайскому облаку, рано или поздно сталкиваются с задержками выполнения сценариев или вообще с необъяснимыми отказами и возникает желание сделать так, чтобы сценарии при исполнении никуда наружу в «облако» не «ходили», а исполнялись в домашней локальной сети.

В интернете на различных тематических форумах описываются и предлагаются множество программных и программно-аппаратных вариантов для решения подобных задач, наиболее популярным и поддерживаемым сообществом является Home Assistant (далее HASS), но его установка и настройка, несмотря на большое количество информации в интернете, может вызвать затруднения у неподготовленного пользователя. Для устройств экосистемы Xiaomi есть готовая HASS интеграция MIOT, которая «из коробки» дает возможность создания локальных и облачных сценариев.

Около двух лет  назад (имеется в виду 2022 год) Xiaomi в новых моделях роутеров (на момент написания статьи BE3600PRO и BE6500PRO) и хабов (Xiaomi Home Hub) начала добавлять свое решение для создания локальных сценариев Mijia Automation Geek Edition и далее я хочу его сравнить именно с HASS.

К очевидным плюсам HASS можно отнести:

  • Гибкость платформы, возможность интеграции устройств различных экосистем

  • Наличие документации и множество примеров использования

  • Поддержка сообщества и энтузиастов

Минусы тоже есть:

  • Необходимость наличия сервера для развертывания HASS и MIOT. Малогабаритные barebone системы, например, Raspberry PI, могут стоит относительно дорого в зависимости от конфигурации, и для их настройки нужно иметь определенные навыки.

  • Относительная сложность подключения новых устройств – извлечение токенов устройств, настройка конфигураций и т.д.

  • Сложность создания локальных сценариев с использованием нетиповых устройств, типа виртуальных панелей.

Mijia Automation имеет свои преимущества:

  • Не требуется отдельный сервер - софт встроен в прошивку хаба

  • Все сценарии только локальные

  • Поддержка почти всех устройств экосистемы Xiaomi «из коробки»

Минусы относительно HASS:

  • Поддерживаются только устройства экосистемы Xiaomi

  • Интерфейс среды только на китайском, работает только в китайском регионе

  • Ограниченные возможности самой среды – только самое необходимое, никаких свойств и конфигураций элементов и блоков.

  • Закрытость системы

  • Полное отсутствие документации.

Как видим, минусов у Mijia Automation перечислено больше чем у HASS, поэтому, на идеальное решение для умного дома среда не претендует, но с моей точки зрения она достаточно интересная и заслуживающая внимания, как удобная для быстрой разработки сложных локальных сценариев особенно если производитель сможет довести ее до ума в будущем – хотя бы сделает поддержку языков, кроме китайского. Эта статья посвящена последнему перечисленному минусу о документации и инструкциях, и я покажу, что в использовании среды Mijia Automation нет ничего сложного.

Описание функционала среды разработки Mijia Automation

С чего начать?

Как я уже писал, китайская (скорее восточная) техно гик идеология устроена таким образом, что самые новые, технологичные и интересные устройства (в т.ч. по цене) они выпускают только для китайского рынка. Именно поэтому большинство пользователей рано или поздно переезжают на китайское облако экосистемы, т.к. глобальные облачные сервисы эти устройства не поддерживают. Xiaomi Home Hub или роутер с функционалом Geek Automation не стали исключением из правил – подключаются только в регионе Китай и по сравнению со списком функций «обычного» хаба или роутера, появился раздел для подключения к среде. .

Если у вас уже есть такое устройство откройте плагин в приложении Mi Home и заходите в раздел «Функция центра управления», там вы увидите IP адрес сервера, ниже отображается OTP код необходимый для входа на основную страницу среды программирования.

Xiaomi Home Hub in Mi Home

Xiaomi Home Hub in Mi Home

После перехода по ссылке открывается страница входа с среду разработки сценариев. Тут надо сказать, что для телефона среда не адаптирована, хотя страница в домашней сети и откроется, и этим можно пользоваться, когда срочно нужно что-то сделать, например, активировать или деактивировать автоматизацию, но работать там, создавать или редактировать какие-то сценарии с разветвленной логикой будет очень неудобно. Поэтому рекомендуется использовать десктоп с большим монитором. При работе на компьютере нужно запустить Chrome браузер, ввести в адресной строке IP-адрес из функционала управления Xiaomi Home Hub откроется страница входа (как на картинке ниже) на которой также необходимо ввести ОТР код из приложения (как показано на картинке выше):

Страница входа

Страница входа

Далее открывается основная страница среды. Как я уже писал выше, к сожалению, в данный момент среда доступна только на китайском языке и только в браузере Chrome, поэтому, рекомендуется использовать на страницах встроенный в Chrome Google переводчик, мне привычнее переводить на английский, т.к. в контексте программирования по терминологии и качеству получается немного лучше и точнее , чем на русском, плюс переменные при переводе страницы не пытаются переводиться на русский. Т.е. далее все описания блоков будут идти по названиям в английском переводе Google переводчика. При авто-переводе иногда наблюдается небольшая проблема – открывается пустая страница и закрывается сессия, видимо, перевод заменяет и текст в ссылках, приходится заходить заново. Поэтому, рекомендуется чаще сохраняться, либо использовать приложения для экранного перевода.  

Главная страница

Главная страница

Основное окно содержит список сценариев пользователя (1), поддерживается фильтрация и сортировка по полям. В правой части строки сценария (2) есть выпадающее меню стандартных действий (3) – переименовать, создать копию, удалить и тумблер переключения состояния сценария. Помимо отключения выполнения всех действий внутри сценария данный тумблер выполняет еще одну очень важную роль – выступает триггером для запуска некоторых блоков, но об этом будет рассказано ниже. В последних версиях прошивки хаба наконец-то появилась полезная функция (4) экспорта всех запрограммированных сценариев в файл и возможность восстановления конфигурации умного дома. В верхнем правом углу (5) есть ссылки на блог, FAQ на китайском и описание изменений в релизах среды. Иногда можно узнать что-нибудь полезное.

Под списком сценариев (6) следует список оборудования, поддерживающего локальные автоматизации с помощью среды. У меня в список попали почти все устройства умного дома (находящиеся в данный момент в онлайне), включая добавленные через Mi Home VEVS неродного региона. По какому принципу какое-то устройство может быть недоступно в среде понять невозможно, будем надеяться, что по мере развития среды недоступные ранее также будут появляться в списке (как это происходит, например, в умном доме Яндекса). Также выборку можно ограничить по размещению или типу устройства.

Список подключенных устройств

Список подключенных устройств

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

Доступные интерфейсы устройства

Доступные интерфейсы устройства

Далее в левой панели еще одно очень полезное нововведение последних прошивок – работа с переменными (7). Среда поддерживает изоляцию данных, переменные делятся на глобальные и локальные. По смыслу локальные работают только внутри сценария, глобальные нужны, когда есть необходимость передать что-то между различными сценариями. Самое интересное, при сохранении сценария среда автоматически чистит локальные неиспользуемые, поэтому, не удивляйтесь, если они вдруг куда-то при сохранении сценария пропали. Страница создания и редактирования локальных переменных:

Работа с глобальными переменными

Работа с глобальными переменными

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

Страница создания автоматизации

Страница создания автоматизации

Основные элементы управления на странице создания автоматизации (модуле);

  1. Палитра функциональных блоков, используемых для создания сценариев. Подробно будут описаны ниже.

  2. Отмена и повтор редактирования.

  3. Вызов экрана работы с локальными переменными.

  4. Выгрузка сценария в картинку (.jpg)

  5. Добавление на экран блока для комментариев.

  6. Вызов в нижней части экрана функционала отладчика сценария.

  7. Вызов в нижней части экрана подсказки по горячим клавишам.

  8. Сохранение программы.

  9. Изменение масштаба элементов на экране.

При создании сценария основной подход, используемый в Mi Home – захват события, анализ и учет условий выполнения, формирование действие в общем сохраняется, но при этом становятся доступны логика и алгоритмы, которые в Mi Home были недоступны.

Mijia Automation Geek Edition это визуальная (no-code) среда разработки, программирование сценариев автоматизаций представляет собой перетаскивание на подложку в центре экрана из панели в левой части блоков-логических элементов и соединение их связями-нитями процессов и условий. Процесс может ветвиться – иметь параллельные нити сценариев.

Ниже приведены описания этих блоков, для некоторых приведены примеры использования. Блоки имеют входные и выходные коннекторы, синим обозначены коннекторы для нитей процесса, зеленым для связи с блоками-условиями. Двухцветные коннекторы могут одновременно выступать как для связи с коннектором процесса, так и коннектором условия. Соединить синий и зеленый коннектор нельзя. Также нельзя соединить два входа или два выхода - строго стрелка из выхода одного блока на вход второго. Блоки триггеры (с которых начинается процесс) не имеют входных коннекторов. Из выходного коннектора могут выходить несколько нитей процесса (ветвление), но нельзя несколько нитей завести во входящий, а если требуется объединение процессов в один результирующий, то необходимо использовать блоки логики описанные ниже «Meets all conditions» (объединение через логическое И) или «Meets any conditions» (объединение через логическое ИЛИ).

В самой среде блоки сгруппированы в шесть групп – Equipment (работа с оборудованием), Time (таймеры и условия по времени), Process (циклы и процессные переключатели и обработчики условий), Logic (процессная логика), Other (то, что не попало в вышеперечисленную классификацию), Variables (группа работы с переменными – триггеры, запросы состояния, функции работы с переменными). Деление весьма, конечно, условное и непонятное, я бы сделал по-другому, но самая интересная из них это последняя группа, она появилась в одной из последних прошивок и позволяет сделать реально полезные вещи, которые будут описаны ниже.

1. Группа Equipment

1.1 Блок захвата события

Блок захвата события

Блок захвата события

Блок захвата события - один из типов триггеров, использующегося для старта процесса сценария, например, по событию изменения температуры на датчике или включения выключения реле или нажатия кнопки. Может формировать и выход процесса и условие выполнения. Указывается с условием при выполнении которого процесс идет дальше. Переключатель в нижней части посередине ограничивает срабатывание триггера одним разом. Сам поток событий формируется аппаратно самим устройством, реализация может быть весьма специфична в зависимости от производителя. Например, разные производители датчиков температуры могут формировать с разным шагом изменения температуры (возможно и 0.1 и 0.5 и 1 градус). Встречал также устройства, которые просто выдают в эфир события генератором. Обычно ни в каких инструкциях к устройству это не описывается, в открытых источниках информации тоже мало, но реальную картину хорошо видно при анализе выполнения сценария при помощи встроенного отладчика сценария (описание работы которого будет приведено ниже).

1.2 Блок запроса показаний и состояния

Блок запроса показаний датчиков и состояния устройства

Блок запроса показаний датчиков и состояния устройства

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

1.3 Блок действия

Блок формирования действия

Блок формирования действия

Блок действия - изменяет статус устройства, изменяет настройки и конфигурации, выполняет аппаратные команды - переключает реле, включает физические действия устройства.

2. Группа Time

2.1 Блок Timing (Таймер)

Таймер

Таймер

Таймер это триггер предназначенный для старта процесса в конкретное время или по расписанию.

2.2 Блок Time Period (Период выполнения)

Условие по периоду выполнения

Условие по периоду выполнения

Time Period является триггером для старта процесса (срабатывает, если текущее время попадает в указанный диапазон) и условием. Как условие подключается, когда необходимо ограничить сценарий или часть сценария по периоду времени. Условие используется, как правило, вместе с блоками, описанными ниже, 3.1 когда-если-то или блоками агрегации условий - 4.2 выполнены все условия или 4.2 выполнено одно из условий.

2.3 Блок Delay (Задержка)

Задержка выполнения

Задержка выполнения

Delay - тут все просто - останавливает нитку процесса на указанный период времени

2.4 Блок State lasted for a while

State lasted for a while

State lasted for a while

State lasted for a while - по смыслу похож на Delay, с той лишь разницей, что создан для обработки условий, формирует выход процесса или выполнение условия в зависимости от времени, которое прошло между обращением к нему на входе. Например, для формирования события - окно открыто 5 секунд. Применяется, также, как и в 2.2 с блоками обработки логики. Ниже приведен синтетический пример, демонстрирующий работу блоков задержек 2.3 и 2.4, изменяя время задержки в блоке Delay можно добиться разных комбинаций работы выходов процессов:

Пример работы с задержками

Пример работы с задержками

2.5 Блок Events occured successively

Events occured successively

Events occured successively

Блок Events occured successively используется для объединения двух событий, которые произошли в течении заданного времени, в одно действие. Например, сработал датчик открытия двери и датчик присутствия в коридоре в течении 5 секунд включаем свет в зале.

3 Группа Process

3.1 Блок When-If-Then

When-If-Then

When-If-Then

When-If-Then - один из основных блоков процессной логики, применяется для проверки заданных условий (через зеленый вход) и формирования позитивного выхода, если проверка прошла успешно и негативного, если проверка завершилась неудачно.

3.2 Блок Cycle

Цикл

Цикл

Cycle - блок предназначен для генерации выходов процесса с заданной частотой, при этом не является (!) стартующим процесс триггером. Для его запуска на вход необходимо подать некое активирующее действие, например, выход из блока 5.2 When this automation is enabled Например, как на картинке ниже. Для остановки цикла генерации действий необходимо использовать второй нижний синий вход.

Пример запуска цикла

Пример запуска цикла

3.3 Блок Trigger at most the specified numbers of times

Trigger at most the specified numbers of times

Trigger at most the specified numbers of times

Trigger at most the specified numbers of times - на самом деле не триггер, а ограничитель количества выполнения циклов сценария в штуках. Например, для включения света при открытии двери один раз в день. Синий нижний вход предназначен для сброса счетчика, например, туда можно подключить выход 2.3 задержки или 2.1 таймера. Ниже приведен синтетический пример реализации данной логики:

Пример работы с ограничителем

Пример работы с ограничителем

3.4 Блок When the specified number of times is reached

When the specified number of times is reached

When the specified number of times is reached

Блок When the specified number of times is reached - внешне похож на 3.3, но в отличии от него, не ограничивает сценарий по количеству событий, а является счетчиком, который при достижении заданной величины событий на входе формирует действие и продолжает процесс или формирует условие. Также, как в 3.3. нижний вход предназначен для сброса счетчика.

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

Пример сценария включения света при двойном нажатии

Пример сценария включения света при двойном нажатии

3.5 Блок Mode Switching

Mode Switching

Mode Switching

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

4. Группа Logic

4.1 Блок When any event occurs

When any event occurs

When any event occurs

When any event occurs - так же один из самых часто используемых блоков, как было написано выше, если стрелки-связи из одного выхода блока для ветвления процесса можно создавать в неограниченном количестве, то обратно сводить ветвления процесса в один можно только через логические блоки. В данном случае процессы складываются в один через логическое ИЛИ. Блока для объединения процессов через логическое И не предусмотрено ввиду низкой вероятности таких событий, но если такая потребность может возникнуть, то для этого существуют блоки для объединения условий описанные ниже.

4.2 Блок Meet any conditions

Meet any conditions

Meet any conditions

Meet any conditions - по смыслу аналогичен блоку 4.1, но предназначен для объединения условий (зеленые стрелки) через логическое ИЛИ. На выходе может формировать и условие и процесс.

4.3 Блок Meet all conditions

Meet all conditions

Meet all conditions

Meet all conditions - предназначен для объединения условий (зеленые стрелки) через логическое И. На выходе может формировать и условие и процесс.

4.4 Блок Status inversion

Status inversion

Status inversion

Status inversion - блок для преобразования статуса условия на обратное или преобразования условия в процесс.

5. Группа Other

5.1 Блок Custom Status

Custom Status

Custom Status

Custom Status - в отличии от 4.4 - преобразование в обратную сторону, нитей процессов в условие.

5.2 Блок When this automation is enabled

When this automation is enabled

When this automation is enabled

When this automation is enabled - блок является триггером для старта сценария и предназначен для взаимодействия автоматизации на основном экране среды (список автоматизаций) и блоков внутри программного модуля. Т.е. при активации тумблера на списке автоматизаций ниже, формируется событие на выходе из блока:

Тумблер активации автоматизации

Тумблер активации автоматизации

6. Группа Variables

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

6.1 Блок Device trigger assignment (Подписка на события)

Подписка на события

Подписка на события

Device trigger assignment (подписка на события) - по сути наследник триггера 1.1 - блока захвата события, с существенным различием - тут он при появлении события присваивает его в указанную переменную, а обработка условий вынесена в отдельные предусмотренный для этого блок 6.4. Переключатель в нижней части посередине ограничивает срабатывание триггера одним разом.

Пример использования. Некоторые производители экосистемы Xiaomi уже начали делать устройства, которые максимально раскрываются в среде Mijia Automation. Например, панель Linptech Touch Screen Switch S2 в которой есть так называемые виртуальные устройства. Выбор устройств пока небольшой - это управление светом, шторами и кондиционером, но данная технология выглядит очень многообещающей.

Палитра виртуальных устройств Linptech Touch Screen Switch S2

Палитра виртуальных устройств Linptech Touch Screen Switch S2
Управление теплым полом в панели Linptech Touch Screen Switch S2

Управление теплым полом в панели Linptech Touch Screen Switch S2

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

Пример управления кондиционером с виртуальной панели

Пример управления кондиционером с виртуальной панели

6.2 Блок Query device and assign values (Запрос показаний в переменную)

Запрос показаний в переменную

Запрос показаний в переменную

Блок Query device and assign values - это наследник блока 1.2, предназначен для запроса показаний датчиков и состояния устройства и назначения эти значений в указанную переменную. В отличии от блока 1.2 функционал анализа условий вынесен в отдельный блок 6.4.

6.3 Блок Variable value update (Захват события обновления переменной).

Захват события обновления переменной

Захват события обновления переменной

Блок Variable value update (Захват события обновления переменной) это триггер для старта процесса, который срабатывает при обновлении переменной и сравнивает значение с указанным условием, формирует выход процесса и условия. Переключатель в нижней части посередине ограничивает срабатывание триггера одним разом.

6.4 Блок Query variable value (Обработка условий)

Работа с условиями

Работа с условиями

Блок Query variable value (Обработка условий) - как такового запроса (Query) тут нет (видимо, некорректное название или перевод), это блок для сравнения переменной с указанными условиями, вынесенный из 1.1 и 1.2 и используемый в связке с 6.1 и 6.2, а также в других местах, где требуется. Формирует выход для успешного и неуспешного выполнения условия.

6.5 Блок работы с числовыми переменными

Операции числовыми переменными

Операции числовыми переменными

Блок работы с числовыми переменными позволяет проводить широкий спектр различных математических вычислений с полученными данными, включая сравнение показаний разных датчиков или установленных на различных панелях целевых значений и текущих показаний устройств. Для того, чтобы вставить в формулу ссылку на переменную введите в строке вычисления знак $ или нажмите на значок (х) и среда откроет за значком список доступных в автоматизации переменных, включая глобальные. При нажатии на значок f(x) открывается список доступных математических функций.

6.6 Блок работы с текстовыми переменными

Операции с текстовыми переменными

Операции с текстовыми переменными

Блок работы с текстовыми переменными предназначен для формирования динамических строк для вывода на панели, которые поддерживают текстовый вывод. При сложении текстовых строк и числовых значений, среда сама выполняет необходимые преобразования типов.

Отладка сценариев

При разработке сценариев очень часто возникает такая ситуация, когда все вроде бы составлено правильно, но автоматизация либо не работает, либо ее поведение отличается от задуманного сценария. И тут сильно может помочь очень полезный и важный инструмент - отладчик сценариев (или debugger), пользоваться которым не составит большого труда и не потребует каких-то тайных знаний. Среда выполнения автоматизаций на каждом шаге логирует свои действия и чтобы увидеть исполнение сценария по шагам необходимо в верхней правой части экрана нажать на значок листа с записями (между значками "Т" и "i"):

Отладка сценариев

Отладка сценариев

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

Интеграция Mijia Automation с облачной средой Mi Home

Как было уже написано выше, сценарии созданные в Mijia Automation хранятся и выполняются локально на хабе и только в домашней сети. Но часто возникает необходимость что-то передать в среду Mi Home или наоборот. Например, вы сделали локальные сценарии с датчиками движения, открытия дверей или вибрации для охраны дома и вам необходимо получать событие постановки или снятия режима охраны, и в обратную сторону, при срабатывании датчиков отсылать уведомления через приложение. Для этого на хабе предусмотрена функция виртуальных событий, с помощью нее можно связать автоматизации в Mijia Automation и Mi Home. Ниже приведен пример, как это можно сделать:

Создание виртуального события в Mijia Automation

Создание виртуального события в Mijia Automation

Блок также поддерживает работу со строковыми переменными - при нажатии на (х) откроется список доступных для использования.

Отсылка уведомления при получении виртуального события

Отсылка уведомления при получении виртуального события

Заключение

Я надеюсь, что в текущей ситуации с полным отсутствием документации по среде Mijia Automation Geek Edition данное руководство будет полезно для того чтобы попробовать сделать первые шаги в использовании или ответить на какие-то вопросы. Если в статье вы обнаружите неточности или там чего-то не хватает, просьба написать мне сообщение или комментарий, я обязательно исправлю или внесу изменения.

Автор: llebedev1975

Источник

* - обязательные к заполнению поля


https://ajax.googleapis.com/ajax/libs/jquery/3.4.1/jquery.min.js