# Интернет вещей с ESP8266 &ndash; быстрый старт ## Постановка задачи Начнем создавать отдельные элементы «Умного дома». Как вы уже поняли наша система будет работать на базе протокола MQTT. Все контроллеры получают доступ к интернету по Wi-Fi, соединяются с MQTT сервером, подписываются на отдельные топики и/или публикуют в топики информацию. Управляющий сервер также подписывается на нужные топики и может по наступлению определенных событий публиковать в топики информацию или отправлять оповещения через интернет каким-либо способом. В дальнейшем вам будет предложено создать несколько элементов «Умного дома», а пока же мы научимся управлять портами ввода-вывода нашего контроллера (хотя это вы уже умеете), и главное научимся работать с протоколом MQTT. Мы будем мигать встроенным светодиодом с помощью MQTT через внешний сервер и управлять им из различных приложений. ## Собираем схему В реальных задачах вам придется собирать некоторую (пусть и достаточно простую) схему устройства. Сейчас же нам будет достаточно светодиода, установленного на плате контроллера WeMos D1. Так что можем сказать, что у нас все собрано ![wemos_for_blink](/assets/images/iot/wemos_for_blink.png) ## Создаем прошивку для микроконтроллера Теперь нужно написть программу. Библиотека для работы с MQTT (<https://github.com/knolleary/pubsubclient>) у нас подключена. Если нет - вернитесь назад и посмотрите как это сделать. Возможно, в ваших задачах потребуется подключать какие-то новые библиотеки, и вы будете делать это самостоятельно. Для начала работы с MQTT скачайте архив [00_led_mqtt][1], содержащий готовый скетч. Распакуйте его (рекомендуем сразу в папку `/home/student/Arduino/`) ![unzip](/assets/images/iot/arduino/led/unzip.png) и откройте его в среде Arduino IDE. ![unzip](/assets/images/iot/arduino/led/00_led_mqtt.gif) Обратите внимание, что в этом примере есть несколько вкладок: `00_led_blink` - содержит известные вам функции `setup()` и `loop()`, определяющие основное поведение любой программы Arduino, а также функцию `callback()`, в которой мы обрабатываем сообщения от MQTT брокера. ```c // // 00_led_blink.ino // #include <ESP8266WiFi.h> #include <PubSubClient.h> #include "config.h" WiFiClient espClient; PubSubClient client(espClient); String clientId = String(ESP.getChipId()); int delayMS = 30000; // Задаержка в мс между публикацией сообщений long lastMsg = 0; // Время публикации предыдущего сообщения (мс) int value = 0; // Переменная для формирования публикуемого сообщения // Функция обработки входящих сообщений void callback(char* topic, byte* payload, unsigned int length) { // Печать информации о полученном сообщенийй Serial.print("Message arrived ["); Serial.print(topic); Serial.print("] "); for (int i = 0; i < length; i++) { Serial.print((char)payload[i]); } Serial.println(); // Если получено сообщение и у нас подписка на несколько топиков, то определяем в каком топике сообщение опубликовано if (strcmp(topic, mqtt_topic_in) == 0) { // Определяем поведение MCU при различных значениях сообщения (payload) if ((char)payload[0] == '0') { digitalWrite(BUILTIN_LED, HIGH); // BUILTIN_LED имеет подтягивающий резистор, HIGH = OFF, LOW = ON } if ((char)payload[0] == '1') { digitalWrite(BUILTIN_LED, LOW); } } } // Функция настройки MCU void setup() { pinMode(BUILTIN_LED, OUTPUT); // Установка BUILTIN_LED как порт вывода digitalWrite(BUILTIN_LED, HIGH); // BUILTIN_LED имеет подтягивающий резистор, HIGH = OFF, LOW = ON Serial.begin(115200); setup_wifi(); client.setServer(mqtt_server, mqtt_port); client.setCallback(callback); } // Основная функция - вызывается на каждой итерации цикла работы MCU void loop() { if (!client.connected()) { reconnect(); } client.loop(); // Публикация сообщения с заданной периодичностью long now = millis(); if (now - lastMsg > delayMS) { lastMsg = now; ++value; // Формирование сообщения и его публикация char msg[200]; snprintf (msg, sizeof(msg), "heartbeat #%ld", value); Serial.print("Publish message: "); Serial.println(msg); client.publish(mqtt_topic_out, msg); } } ``` Файл `config.h` содержит в себе основные настройки. Приведите его в соответствие с указаниями инструктора. ```c // // config.h // // Настройки WiFi #define wifi_ssid "804.Guest" #define wifi_pass "guest67n23" // Сервер MQTT #define mqtt_server "192.168.80.100" #define mqtt_port 1883 #define mqtt_login "eecs-susu" #define mqtt_pass "IoT_2019" // MQTT топики #define mqtt_topic_status "esp8266/15/status" #define mqtt_topic_out "esp8266/15/heartbeat" #define mqtt_topic_in "esp8266/15/led" ``` В файле `functions.ino` размещены функции, которые потребуются при выполнении всех заданий. Они будут мало чем отличаться, но если возникнет необходимость их изменить, то комментарии к коду подскажут что делать. ```c // // functions.ino // // Функция установления соединения по WiFi void setup_wifi() { delay(10); Serial.println(); Serial.print(F("Connecting to ")); Serial.println(wifi_ssid); Serial.println(wifi_pass); WiFi.begin(wifi_ssid, wifi_pass); while (WiFi.status() != WL_CONNECTED) { delay(500); Serial.println(F(".")); WiFi.printDiag(Serial); } randomSeed(micros()); Serial.println(""); Serial.println(F("WiFi connected")); Serial.println(F("IP address: ")); Serial.println(WiFi.localIP()); } // Функция установления подключения к MQTT брокеру void reconnect() { while (!client.connected()) { Serial.println(F("Attempting MQTT connection...")); Serial.print(F("Client ID:")); Serial.print(clientId); Serial.print(F(" ")); Serial.print(mqtt_login); Serial.print(F(" ")); Serial.print(mqtt_pass); Serial.print(F(" ")); if (client.connect(clientId.c_str(), mqtt_login, mqtt_pass)) { Serial.println(F("connected")); // Публикация сообщения с идентификаторм клиента в топик, заданный значением 'mqtt_topic_status' client.publish(mqtt_topic_status, clientId.c_str()); // Подписка на сообщения в топике, заданном значением mqtt_topic_in client.subscribe(mqtt_topic_in); // Если нужно подписаться на несколько топиков, то для каждого из них вызываем client.subscribe() } else { Serial.print(F("failed, rc=")); Serial.print(client.state()); Serial.println(F("try again in 5 seconds")); delay(5000); } } } ``` Чтобы во время нашей работы команды не мешали друг другу, измените в файле `config.h` MQTT топики, с которыми работаете - вместо числа 15 запишите номер вашей команды! Например, для команды №8 эти строки буду выглядеть так: ```c // MQTT топики #define mqtt_topic_status "esp8266/8/status" #define mqtt_topic_out "esp8266/8/heartbeat" #define mqtt_topic_in "esp8266/8/led" ``` После компиляции программы и заливки ее в контроллер вы сможете, направляя 1 или 0 в топик, указанный в `mqtt_topic_in`, управлять со своего компьютера, мобильного телефона или через WEB поведением светодиода. При этом в топике, указанном в `mqtt_topic_out` будут периодически появляться сообщения от контроллера, сигнализирующие что он на связи. [1]: https://aiu.susu.ru/assets/components/fileattach/connector.php?action=web/download&ctx=web&fid=VXXL6gCr6EhMYDDElEhj_TJ2eP1OTuWO ## Работа с MQTT Самым простым клиентом будет **MQTT.fx**. Его можно скачать с <https://mqttfx.jensd.de/>. Для наших компьютеров понадобится 64-разрядный пакет для Debian. ![wemos_for_blink](/assets/images/iot/mqttfx_download.png) Скачайте его в каталог `Загрузки`, после чего запустите приложение **Terminal** (нажмите на клавиатуре комбинацию клавиш Ctrl+Alt+T). В терминале наберите: ```sh sudo dpkg -i ~/Загрузки/mqttfx-1.7.1-64bit.deb ``` Во время ввода этой команды вас попросят ввести пароль - его вам скажет инструктор. Обратите внимание, что при вводе пароля ни он, ни какие другие символы (например, звездочки) не отображаются! Если все прошло успешно - терминал можно закрыть, он нам больше не понадобится. Далее, запускаем **MQTT.fx**. Теперь необходимо настроить подключения к серверу, для чего следует нажать на иконку с шестерёнкой. ![mqttfx_01](/assets/images/iot/mqttfx_01.png) Настроим соединение ![mqttfx_02](/assets/images/iot/mqttfx_02.png) Для этого следует: 1. Добавить новое соединение 2. Указать его название 3. Ввести имя сервера (предоставит инструктор) 4. Ввести порт на сервере (предоставит инструктор) 5. Сгенерировать уникальный ИД клиента 6. Переключиться на ввод логина и пароля! ![mqttfx_03](/assets/images/iot/mqttfx_03.png) 7. Ввести логин (предоставит инструктор) 8. Ввести пароль (предоставит инструктор) И сохранить изменения нажатием кнопки **ОК**. Далее требуется подключиться к серверу нажатием кнопки **Connect** ### Публикация и подписка Теперь для того, чтобы управлять светодиодом достаточно на вкладке **Publish** ввести имя топика, указанное в настройках прошивки в значении параметра **mqtt_topic_in** (у нас это `esp8266/15/led`), в текстовое поле написать **0** или **1** и нажать кнопку **Publish**. Остальные настройки менять не надо. ![mqttfx_pub](/assets/images/iot/mqttfx_pub.png) Для контроля работоспособности устройства на вкладке **Subscribe** можно подписаться на топики, указанные в параметрах **mqtt_topic_status** и **mqtt_topic_out** ![mqttfx_sub](/assets/images/iot/mqttfx_sub.png) ## Управляем со смартфона MQTT клиент может быть установлен и на смартфоне, а значит можно управлять нашим устройством прямо с него. Для Android есть достаточно много таких клиентов. Вот лишь несколько: + [IoT MQTT Panel](https://play.google.com/store/apps/details?id=snr.lab.iotmqttpanel.prod) + [Linear MQTT Dashboard](https://play.google.com/store/apps/details?id=com.ravendmaster.linearmqttdashboard) + [MQTT Dash \(IoT, Smart Home\)](https://play.google.com/store/apps/details?id=net.routix.mqttdash) C iOS дела обстоят несколько хуже - вот список того, что удалось вообще найти: + [MQTTool](https://itunes.apple.com/ru/app/mqttool/id1085976398?mt=8) + [IoT OnOff](https://itunes.apple.com/ru/app/iot-onoff/id1267226555?mt=8) + [MQTT Terminal](https://itunes.apple.com/ru/app/mqtt-terminal/id1404331673?mt=8) + [Cayenne - IoT Project Builder](https://itunes.apple.com/ru/app/cayenne-iot-project-builder/id1057997711?mt=8) + [Visual Home](https://itunes.apple.com/ru/app/visual-home/id1347968525?mt=8) Рассмотрим на примере [IoT MQTT Panel](https://play.google.com/store/apps/details?id=snr.lab.iotmqttpanel.prod) как создать конфигурацию приложения для управления нашим устройством. Разумется приложение нужно установить. Можно воспользоваться QR-кодом для доступа к [ ![Google.Play](https://www.gstatic.com/android/market_images/web/play_prism_hlock_1x.png) ](https://play.google.com/store) ![iot_mqtt_panel_qr](/assets/images/iot/android/iot_mqtt_panel_qr.svg) После запуска приложения будет предложено создать подключение ![Andr_01](/assets/images/iot/android/a01.png) Необходимо указать имя соединения, придумать идентификатор клиента и задать параметры MQTT брокера, как и в случае с MQTT.fx. ![Andr_02](/assets/images/iot/android/a02.png) Для задания имени пользователя и пароля необходимо раскрыть раздел **Advanced options** ![Andr_03](/assets/images/iot/android/a03.png) Так как это у нас первый запуск приложения, то нам сразу же будет предложено добавить новое устройство, что мы и сделаем (у нас оно называется IoT course) ![Andr_04](/assets/images/iot/android/a04.png) Теперь соединение у нас создано, нажмем на его имя (**SmartHome**) ![Andr_05](/assets/images/iot/android/a05.png) Нас предупредят, что наше устройство не содержит ни одной панели управления - нажмем на **Add Panel** ![Andr_06](/assets/images/iot/android/a06.png) Выберем переключатель (**Switch**) ![Andr_07](/assets/images/iot/android/a07.png) и настроем его - укажем имя элемента, топик (используйте номер своей команды вместо указанного на рисунке), а также значения для состояний **on** и **off** Пролистываем экран до конца, и нажимаем **Create** ![Andr_08](/assets/images/iot/android/a08.png) ![Andr_09](/assets/images/iot/android/a09.png) Получившийся элемент занимает слишком много места на экране, поэтому уменьшим его ширину ![Andr_10](/assets/images/iot/android/a10.png) ![Andr_11](/assets/images/iot/android/a11.png) Добавим еще одну панель к нашему устройству - нажмем на кнопку **+** ![Andr_12](/assets/images/iot/android/a12.png) Выберем **LED Indicator** и настроим его ![Andr_13](/assets/images/iot/android/a13.png) ![Andr_14](/assets/images/iot/android/a14.png) Теперь если установить соединение, то мы сможем с мобильного телефона включать и отключать светодиод на плате WeMos D1, а его состояние будет отображаться на экране ![Andr_15](/assets/images/iot/android/a15.png) ![Andr_16](/assets/images/iot/android/a16.png) Мы можем построить граяик изменения некоторой величины. Но светодиод и переключатель могут принимать всего два состояния - включено и выключено, а потому график получится весьма скучным. Наш MQTT брокер принимает данные не только от ваших контроллеров WeMos D1, но и от других датчиков: температуры и влажности. Для получения информации с них необходимо подписаться на топик `devices/lora/807b859000282cbe` (если что-то изменится, то об этом скажет инструктор). Добавим к устройству панель **Line Graph** для отображения температуры в помещении. Данные от датчика передаются в формате JSON в объекте **data** ![Andr_17](/assets/images/iot/android/a17.png) ![Andr_18](/assets/images/iot/android/a18.png) ![Andr_19](/assets/images/iot/android/a19.png) И добавим **Gauge** для отображения влажности ![Andr_20](/assets/images/iot/android/a20.png) ![Andr_21](/assets/images/iot/android/a21.png) ![Andr_22](/assets/images/iot/android/a22.png) Еще добавим **Text Log** и настроем его на вывод сообщений от наших контроллеров. Обратите внимание, что здесь мы использовали шаблон, и у нас будут отображаться все события, связанные со светодиодами всех контроллеров, которые у нас задействованы сегодня. ![Andr_23](/assets/images/iot/android/a23.png) ![Andr_24](/assets/images/iot/android/a24.png) Наше готовое приложение ![Andr_25](/assets/images/iot/android/a25.png) ## Серверное приложение ### Установка Node-RED Возможно, что **Node-RED** уже был установлен, и часть действий, описанных ниже - пустая трата времени. Тем не менее пройти все шаги все равно будет полезным. Чтобы предыдущие настройки нам не мешались - удалим их командой ```bash rm -rf ~/.node-red/ ``` Установим **NodeJS** и программу управления пакетами **npm**, для чего запустим **Terminal** и в нем введем: ```bash sudo apt install nodejs npm ``` Установим собственно сервер **Node-RED** и вспомогательную утилиту **node-red-admin**. ```bash sudo npm install -g --unsafe-perm node-red node-red-admin ``` Менеджер **npm** обычно устанавливает пакеты в текущий каталог. В данной команде использован флаг `–g (globally)`, который выполнит глобальную установку указанных пакетов и поместит их в стандартный каталог системы, например в `/usr/local/bin`. Флаг `—unsafe-perm` помогает избежать некоторых ошибок, которые могут возникнуть при попытке npm скомпилировать встроенные модули (написанные на компилируемых языках, например C или C++). Если установка завершилась успешно, то должно будет выглядеть примерно так: ![nodered_install](/assets/images/iot/nodered_install.png) Node-RED использует порт 1880 - разрешим подключения по этому порту ```bash sudo ufw allow 1880 ``` Заодно узнаем какой у нашего компьютера IP-адрес: ```bash ifconfig | grep 'inet 192.' ``` ![ifconfig](/assets/images/iot/ifconfig.png) В нашем случае - это **192.168.1.41**. Если же в ответ вы получите сообщение, что утилита `ifconfig` не установлена, установите ее командой ```bash sudo apt-get install net-tools ``` и повторите предыдущий запрос. Запустим Node-RED командой ```bash node-red ``` В терминале появится приветственное сообщение типа *Welcome to Node-RED* и информационное сообщение **Server now running**. ![nodered_run](/assets/images/iot/nodered_run.png) Теперь запускаем любой браузер и переходим по адресу, который мы определили ранее (**192.168.1.41**), и задаем номер порта 1880: <http://192.168.1.41:1880> ![nodered_browser](/assets/images/iot/nodered_browser.png) Чтобы остановить сервер, в терминале, в котором запускали Node-RED, нужно нажать сочетание клавиш Ctrl+C. Но мы пока этого делать не будем. ### Интерфейс Node-RED Основная единица работы с логикой приложения для Node-RED - это **поток** (**flow**). Он состоит из **узлов** (**node**) - блоков (минимальных единиц логики), которые можно собирать вместе в большую и сложную систему обработки событий. С левой стороны экрана находится палитра элементов с группой блоков. Группы блоков разделены на подгруппы по функциональности. Если выбрать узел, то справа на **боковой панели**, во вкладке **info** будет показана информация о том, как этот узел работает. В центре экрана находится основная рабочая область, где создаются потоки. Над боковой панелью имеется кнопка **Deploy**, предназначенная для развертывания системы автоматизации - запуска получившейся программы на исполнение. ![nodered_sections](/assets/images/iot/nodered_sections.png) Нам нужно будет сделать еще несколько предварительных настроек. Сначала надо установить дополнение `node-red-dashboard`. В правом верхнем углу страницы расположена кнопка вызова меню. Нас интересует меню **Manage palette**. ![nodered_add_ui_menu](/assets/images/iot/nodered_add_ui_menu.png) В появившемся окне по вертикаливыберем раздел **Palette**, а по горизонтали - раздел **Install** ![nodered_add_ui_install](/assets/images/iot/nodered_add_ui_install.png) В поле поиска введите `node-red-dashboard` и нажмите **Install**, расположенную рядом с найденным компонентом. В появившемся окне нажмите **Install** ![nodered_add_ui_confirm](/assets/images/iot/nodered_add_ui_confirm.png) После завершения установки можно закрыть всплывающие окна (кнопка **Close**) и перейти к созданию приложения. ### Базовые узлы Узлы в палитре группируются по разделам. Самые важные для работы приложения разделы: - **input** - поступление входящих сигналов - **output** - отправляют сигналы в результате принятых решений - **function** - позволяют применить дополнительные преобразования к данным и принимать решения - **social** - отсылка/прием сообщений (в базовой поставке) с email и twitter, после установки дополнительных плагинов можно расширить возможности еще больше. - **dashboard** - появляется после установки `node-red-dashboard`, содержит компоненты для постройки визуального интерфейса. ### Наш первый поток Ранее мы настраивали работу контроллера с сервером по MQTT, теперь сделаем полный цикл настройки для работы с помощью Node-RED. Первым делом надо добавить кнопку, которая будет зажигать светодиод. Из палитры в разделе **dashboard** с помощью перетаскивания добавляем два узла **button** ![](/assets/images/iot/nodered/node_dashboard_button.png) - для включения и выключения, а из раздела **output** узел **mqtt** ![](/assets/images/iot/nodered/node_output_mqtt.png) Потом соединяем выходы узлов **button** со входом узла **mqtt** мышкой. ![](/assets/images/iot/nodered/flow_two_button_mqtt.png) Двойным щелчком по верхнему узлу **button** откроем диалог редактирования. ![](/assets/images/iot/nodered/node_input_button_edit_before_on.png) Выбираем **Add new ui_group...** и кнопкой ![](/assets/images/iot/nodered/node_input_button_pencil.png) открываем диалог создания новой группы элементов, в которой будет размещаться наша кнопка. ![](/assets/images/iot/nodered/node_input_button_add_dashboard_group.png) Дадим этой группе имя **First ROW** и аналогичным образом добавим колонку (**Tab**) ![](/assets/images/iot/nodered/node_input_button_add_dashboard_tab.png) Указывае имя (**Home**) и жмем **Add**, закрывая диалог добавления колонки. Аналогично, нажатием **Add** закроем диалог создания группы элементов. Теперь для элемента **button**, с которым мы работаем, укажем метку (**Label**), подсказку (**Tooltip**), и самое главное - значение, которое будет отсылаться при нажатии на эту кнопку - **Payload**, а также **Name**. В итоге диалог будет выглядеть так: ![](/assets/images/iot/nodered/node_input_button_edit_after_on.png) Закрываем его нажатием **Done**. Аналогичным образом нужно настроить нижнюю кнопку (только создавать новые группы и столбцы не надо, достаточно их просто выбрать из выпадающего меню): ![](/assets/images/iot/nodered/node_input_button_edit_after_off.png) Для узла MQTT потребуется настроить **Server** - аналогично рассмотренным выше случаям выбираем **Add new mqtt-brocker...** ![](/assets/images/iot/nodered/node_output_mqtt_edit_before.png) И настраиваем его параметры на вкладке **Connection** ![](/assets/images/iot/nodered/node_output_mqtt_server_connection.png) и вкладке **Security** ![](/assets/images/iot/nodered/node_output_mqtt_server_security.png) Эти значения вам уже должны быть известны - они сегодня использовались уже много раз. Также для узла **mqtt** необходимо указать **Topic**, куда он будет отсылать значения (**Topic** тот же, что и в прошивке в параметре **mqtt_topic_in**), и еще укажем имя (**Name**), чтобы легко отыскать этот блок в потоке. ![](/assets/images/iot/nodered/node_output_mqtt_edit_after.png) Чтобы сразу посмотреть на результат, можно нажать кнопку **Deploy** ![](/assets/images/iot/nodered/menu_deploy.png). Это сохраняет текущий поток и применяет настройки на сервере. ![](/assets/images/iot/nodered/flow_two_button_mqtt_connected.png) Чтобы посмотреть результат выберите в меню пункт **View > Dashboard** ![](/assets/images/iot/nodered/menu_view_dashboard.png) а затем на боковой панели на вкладке **Site** воспользуйтесь кнопкой ![](/assets/images/iot/nodered/button_dashboard_out.png) для перехода к графическому интерфейсу. Заодно на этой же панели **dashboard** во вкладках можно настроить дополнительные параметры отображения. ![](/assets/images/iot/nodered/menu_dashboard_site.png) Вообще, хорошей идеей будет держать две вкладки открытыми одновременно - с редактором и графическим интерфейсом. ![](/assets/images/iot/nodered/dashboard_two_buttons.png) Если запустить **MQTT.fx**, то можно будет наблюдать как при нажатии кнопок в браузере на MQTT сервер отправляется значение нажатой кнопки. Если включен контроллер и все правильно настроено, то зажигающийся светодиод можно будет наблюдать и на нем. Время реакции на команду будет менее 1 секунды. ### Добавим график Теперь дополним наш поток узлом для приёма сообщений - **input/mqtt** ![](/assets/images/iot/nodered/node_input_mqtt.png) и узлом для вывода графики **dashboard/chart** ![](/assets/images/iot/nodered/node_dashboard_chart.png) В итоге должно получиться так (**параметры сервера и топика не забываем использовать свои**): **input/mqtt:** ![](/assets/images/iot/nodered/node_input_mqtt_edit.png) **dashboard/chart:** ![](/assets/images/iot/nodered/node_dashboard_chart_edit.png) Так как данные у нас передаются в формате JSON, то нам надо их декодировать. С этой целью добавим узел **function/json** ![](/assets/images/iot/nodered/node_function_json.png) и установим его параметры следующим образом: ![](/assets/images/iot/nodered/node_function_json_edit.png) В итоге на выходе этого блока у нас будет получаться JavaScript-объект, из которого нам нужно получить значение поля **temperature**. Добавим еще один блок - **function/function** ![](/assets/images/iot/nodered/node_function_function.png) и напишем для него небольшой код: ```javascript var value = msg.payload.data.temperature; msg.payload = value; return msg; ``` Должно получится так: ![](/assets/images/iot/nodered/node_function_function_edit.png) После нажатия **Deploy** ![](/assets/images/iot/nodered/menu_deploy.png) должно получиться примерно так: ![](/assets/images/iot/nodered/flow_two_button_mqtt_chart.png) А в графическом интерфейсе (не забываем обновить страницу нажатием **F5** на клавиатуре): ![](/assets/images/iot/nodered/dashboard_two_buttons_chart.png) Конечно, более простым методом будет сделать всё управление единственным светодиодом при помощи одной кнопки, для этого есть **dashboard/switch** ![](/assets/images/iot/nodered/node_dashboard_switch.png): ![](/assets/images/iot/nodered/node_dashboard_switch_edit.png) ![](/assets/images/iot/nodered/flow_two_buttons_chart_switch.png) Не забываем про **Deploy** ![](/assets/images/iot/nodered/menu_deploy.png) Результат: ![](/assets/images/iot/nodered/dashboard_two_buttons_chart_switch.png) Если потребуется изменить порядок, добавить группы, колонки или ссылки, изменить размещение визуальных компонентов на экране, можно использовать **sidebar dashboard** и на вкладке **Layout** настроить всё: ![](/assets/images/iot/nodered/menu_dashboard_layout.png) Так как ваш смартфон и сервер **Node-RED** сейчас фактически находятся в одной локальной сети, то вы можете подключиться со смартфона к вашему серверу, используя любой браузер, вводя в адресной строке те же самые данные, что и в браузере на компьютере: ```bash 192.168.1.41:1880/ui ``` [**<<< Назад**](iot/summer)&nbsp;|&nbsp;[**Далее >>>**](iot/summer/tasks)