## Серверное приложение
В 2016 году IBM опубликовала свой внутренний проект под названием [Node-RED](https://nodered.org) с открытым исходным кодом.
Это веб-приложение с визуальным редактором программирования, которое позволяет организовывать взаимодействие датчиков и исполнительных механизмов.
Конечно, создавая устройства Интернета вещей без программирования не обойтись, но с Node-RED можно тратить больше времени на создание классных вещей,
а не тратить бесчисленные часы на написание кода.
![Node-RED](/assets/images/iot/nodered_flow.png "Node-RED")
При помощи Node-RED можно легко:
- получить доступ к портам ввода/вывода микроконтроллера;
- устанавливать соединения с другими платами (Arduino, ESP8266 и т.д.);
- создавать адаптивный графический интерфейс пользователя для различных проектов;
- осуществлять связь со сторонними сервисами (IFTTT.com, Adafruit.io, Thing Speak и т.д.);
- получать данные из Интернета (прогноз погоды, цены на акции, электронные письма и т.д.);
- создавать события, запускаемые по времени;
- хранить и извлекать данные из баз данных.
Разработка в Node-RED ведется через обыкновенный браузер, а само ядро Node-RED можно запустить на различных платформах:
в облаке, на сервере, на обычном ПК или даже Raspberry Pi (или аналогичных).
Получившийся пользовательский интерфейс также доступен через браузер.
![Node-RED](/assets/images/iot/nodered_ui.png "Интерфейс пользователя, созданный в Node-RED")
Node-RED удобно использовать на шлюзах между различными сетями устройств Интернета вещей,
функционирующих на собственных, как правило, более простых протоколах и традиционным интернетом, построенных на TCP/IP, UDP.
В этом случае он позволит более оптимально использовать свободные ресурсы шлюза, работающего, как правило, на Linux.
Тем не менее, Node-RED можно запустить и на обычном компьютере (как x86, так и x64) под управлением операционной системы [Windows](https://nodered.org/docs/getting-started/windows).
В рамках же данного практикума рассмотрим работу с Node-RED под Linux (в нашем случае установлена Ubuntu 18.04 LTS).
### Установка Node-RED
Возможно, что **Node-RED** уже был установлен, и часть действий, описанных ниже - пустая трата времени. Тем не менее пройти все шаги все равно будет полезным.
Чтобы предыдущие настройки нам не мешались - удалим их командой
```bash
rm -rf ~/.node-red/
```
Также удалим (если установлена) предыдуущую версию `nodejs`
```bash
sudo apt remove nodejs
```
Теперь установим последнюю версию **NodeJS** с долгосрочной поддержкой и программу управления пакетами **npm**, для чего в терминале введем:
```bash
curl -fsSL https://deb.nodesource.com/setup_lts.x | sudo -E bash -
sudo apt install -y nodejs
```
Далее установим собственно сервер **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++).
Node-RED использует порт 1880 - разрешим подключения по этому порту
```bash
sudo ufw allow 1880
```
Заодно узнаем какой у нашего компьютера IP-адрес:
```bash
hostname -I
```
![hostname](/assets/images/iot/hostname.png)
В нашем случае - это **192.168.1.41**.
Запустим 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:
![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.
![](/assets/images/iot/wemos_rgb.png )
![](/assets/images/iot/fake_lamp/fake_lamp_logo.png)
Мы также создавали приложение, которое могло управлять этой лампой со смартфона. Теперь же сделаем простое управление при помощи серверной программы и визуального программирования!
Первым делом надо добавить кнопку, которая будет включать лампочку.
Из палитры в разделе **dashboard** с помощью перетаскивания добавляем два узла **button** ![](/assets/images/iot/nodered/node_dashboard_button.png) - для включения и выключения,
а из раздела **output** узел **mqtt out** ![](/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-2.png)
Закрываем его нажатием **Done**.
Аналогичным образом нужно настроить нижнюю кнопку (только создавать новые группы и столбцы не надо, достаточно их просто выбрать из выпадающего меню):
![](/assets/images/iot/nodered/node_input_button_edit_after_off-2.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**, куда он будет отсылать значения
(например, виртуальная лампочка, обсуждаемая в предыдущих заданиях курса, для управления использует топик `iot_practice/5404/lamp`,
где 5404 - уникальный идентификатор лампочки, совпадающий с идентификатором пользователя в системе обучения IT Академии Samsung).
И еще укажем имя (**Name**), чтобы легко отыскать этот блок в потоке.
![](/assets/images/iot/nodered/node_output_mqtt_edit_after-2.png)
Чтобы сразу посмотреть на результат, можно нажать кнопку **Deploy** ![](/assets/images/iot/nodered/menu_deploy.png).
Это сохраняет текущий поток и применяет настройки на сервере.
![](/assets/images/iot/nodered/flow_two_button_mqtt_connected-2.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 сервер отправляется значение нажатой кнопки,
а сама лампочка включается и выключается в зависимости от переданной команды.
Конечно, более простой метод сделать управление лампой - это управление при помощи одной кнопки.
Для этого в **Node-RED** есть **dashboard/switch** ![](/assets/images/iot/nodered/node_dashboard_switch.png), разобраться в применении которого самостоятельно не составит большого труда.
### Добавим график
Так как наша "умная лампочка" может менять уровень своей яркости, то добавим в наше серверное приложение возможность отображать этот уровень.
К нашему потоку потребуется добавить узел для приёма сообщений - **mqtt in** ![](/assets/images/iot/nodered/node_input_mqtt.png) в разделе **input** и
узел для вывода графики **chart** ![](/assets/images/iot/nodered/node_dashboard_chart.png) в разделе **dashboard**.
В итоге должно получиться так (**параметры сервера и топика не забываем использовать свои**):
**input/mqtt:**
![](/assets/images/iot/nodered/node_input_mqtt_edit-2.png)
**dashboard/chart:**
![](/assets/images/iot/nodered/node_dashboard_chart_edit-2.png)
Соединяем выход узла **mqtt in** со входом **chart**, и после нажатия кнопки **Deploy** ![](/assets/images/iot/nodered/menu_deploy.png) должно получиться примерно так:
![](/assets/images/iot/nodered/flow_two_button_mqtt_chart-2.png)
А в графическом интерфейсе (не забываем обновить страницу нажатием **F5** на клавиатуре):
![](/assets/images/iot/nodered/dashboard_two_buttons_chart-2.png)
Если потребуется изменить порядок, добавить группы, колонки или ссылки, изменить размещение визуальных компонентов на экране, можно использовать **sidebar dashboard** и на вкладке **Layout** настроить всё:
![](/assets/images/iot/nodered/menu_dashboard_layout.png)
### Автоматическое изменение яркости
Во время одного из предыдущих практикумов у вас было организовано взаимодействие "вещей".
Тогда мы использовали приложение **Sensor Node Free** для передачи показаний с датчика освещенности смартфона под управлением операционной системы Android.
При этом чем ярче освещен датчик телефона, тем тусклее светила лампочка.
![](/assets/images/iot/sensor_node/sensor_node_diagramm.png)
На самом деле за реализацию этого эффекта на сервере отвечала небольшая функция, которую мы сейчас и повторим.
Добавим два узла **mqtt**. Только один - это вход, а второй - выход.
Вход свяжем с топиком, в который отправляет сообщения телефон (`iot_practice/5404/sensornode/LightIntensity/x`):
![](/assets/images/iot/nodered/node_input_mqtt2_edit-2.png)
Выходной узел **mqtt** будет передавать сообщения в топик управления яркостью нашей лампочки (`iot_practice/5404/lamp/value`):
![](/assets/images/iot/nodered/node_output_mqtt_edit-2.png)
Добавим еще один блок - **function/function** ![](/assets/images/iot/nodered/node_function_function.png), зададим ему имя Dimmer, и напишем для него небольшой код на javascript:
```javascript
var sensor_max = 10000; //The really max value is 32768
var sensor = Math.floor(msg.payload);
var topics = msg.topic.split('/');
topics.splice(2);
topic = topics.join('/');
msg.topic = topic + '/lamp/value';
var val = sensor_max - sensor;
val = (val < 0)? 0 : val;
msg.payload = Math.floor((100.0/sensor_max)*val);
return msg;
```
Должно получится так:
![](/assets/images/iot/nodered/node_function_function_edit-2.png)
Не забываем про **Deploy** ![](/assets/images/iot/nodered/menu_deploy.png)
Результат:
![](/assets/images/iot/nodered/dashboard_two_buttons_chart_function-2.png)
### Задание
Доработайте серверное приложение таким образом, чтобы работа с виртуальной "умной" лампочкой была полнофункциональна (включение, отключение, ручное диммирование, режим RGB с возможностью задания цвета).