
Электроника плотно укоренилась в нашей жизни. И речь идёт не о повседневном пользовании благами цивилизации. Мы говорим о тех моментах, когда устройства, созданные на аломощных и недорогих компонентах, решают довольно большой спектр повседневных задач. Они омогают нам с бытом, следят за безопасностью и контролируют наше жилое пространство.
С чего началось
Решил я с приближением зимнего периода, понаблюдать за температурными параметрами в своей квартире и определить качество отопления, если можно так сказать. Если рассмотреть идею с точки зрения АСУ, то нижний уровень будут занимать датчики температуры, средний уровень - Arduino UNO. И верхний - это два варианта SCADA.
Два температурных датчика, которые уже были у меня в наличии, оказались как нельзя кстати. Приведенный пример построен на одном датчике DS18B20 (1-wire) — показать основной принцип. В дальнейшем, без труда можно добавлять любое количество датчиков. Крепить их в необходимых точках и считывать этот физический мир ?. Задача на самом деле довольно тривиальна с учетом наличия большого числа IoT платформ. Но лично мне хотелось получить от процесса больше свободы. Иметь возможность не только получать данные на готовый UI, но и сделать этот интерфейс, что называется, с нуля. Но все же, простой вариант я тоже опишу.
В любом случае для нижнего уровня оба варианта предполагают написание скетча, который будет выполнять сразу несколько задач:
устанавливать Ethernet соединение
опрашивать датчики
отправлять данные по протоколу MQTT брокеру
MQTT как нельзя лучше подходит для таких задач. В названии статьи сама суть его работы.
. Протокол создавался как способ поддержания связи между машинами в сетях с ограниченной пропускной способностью или с непредсказуемой связью. [1]
Более подробно техническую сторону MQTT можно почитать тут:
MQTT хорошо себя зарекомендовал как раз в сфере домашней автоматизации и систем IoT.

Данные будут поступать или на IoT платформу или на любого клиента. Я в качестве таковых использовал «Дом с Алисой» и одну из платформ для облачных решений в области IoT, MQTT-брокер «wqtt.ru». Он предоставляет возможность легкой интеграции с «Дом с Алисой». Достаточно прост авторизоваться в системе через аккаунт Яндекса. Далее в приложении
выбрать сервис WQTT. https://rightech.io/ - версия верхнего уровня представляет собой уже готовое решение - облачный сервис для интернета вещей. Имеется дружелюбный мануал по настройке связи с нижним уровнем, добавлению сущностей и обработки событий.

Второй вариант более сложный, с точки зрения клиент-серверной части, но, так как я сам занимаюсь Javascript и NodeJS, мне он показался интереснее как для примера, так и для повышения моего скила, как разработчика IoT.
Набор датчиков и скетч - тот же.
На любом арендованном сервере разворачиваем NodeJs.
Устанавливаем фреймворк Express, который позволит создать гибко настраиваемую клиентскую часть и даст нам полную свободу действий по написанию нашего веб-интерфейса (у хостера есть хорошая документация по установке).
Данные мы будем передавать также по протоколу MQTT, а на серверной стороне использовать JSON, чтоб AJAX-запросами тянуть данные на страничку.

По умолчанию, Express работает с шаблонизатором PUG. Вообще, шаблон это такой крутой инструмент, который, при правильном использовании, весомо освобождает время разработчика. Зачем повторять кусочки кода, если можно их превратить в некий паттерн и "дергать" по мере необходимости. После установки Express у нас автоматически создалась структура папок, шаблонов и статических директив.
Основное волшебство происходит на серверах...
Стоит хотя бы в каком-то понятном виде получить данные с Arduino. Напомню, что протокол MQTT устроен по принципу подписок и топиков. Для Node JS имеется множество библиотек и MQTT - не исключение. К библиотекам, как правило, прилагаются понятные мануалы и примеры использования. Недостающая информация легко гуглится. Создаем файл библиотеки в папке /lib и экспортируем его в основной файл NodeJS. В основном файле app. js вызываем библиотеку mq.js. После всех манипуляций, в консоли вы должны получить данные с Arduino. Если все получилось, это пол пути, причем успешного!). ?
Код на сервере:
// подключаем необходимые библеотеки и модули var createError = require("http-errors"); var express = require("express"); var path = require("path"); var cookieParser = require("cookie-parser"); var logger = require("morgan"); var indexRouter = require("./routes/index"); var usersRouter = require("./routes/users"); var testRouter = require("./routes/test"); var mq = require("./lib/mq.js"); mq.mq(); var {tempHot}=require('./lib/mq.js'); app.listen(80); app.set("views", path.join(__dirname, "views")); app.set("view engine", "pug"); app.use(logger("dev")); app.use(express.json()); app.use(express.urlencoded({ extended: false })); app.use(cookieParser()); app.use(express.static(path.join(__dirname, "public"))); app.use(express.static(path.join(__dirname, "lib"))); //обработка GET-запроса app.use("/", indexRouter); app.use("/users", usersRouter); app.use("/test", testRouter); app.get('/data', (req, res) => { res.setHeader('Content-Type', 'text/html'); res.write('<!DOCTYPE html>'); res.write('<html>'); res.write('<head>'); res.write('<title>Hello Node.js</title>'); res.write('<meta charset="utf-8" />'); res.write('</head>'); res.write(tempHot, ()=>{ console.log(tempHot) }); res.write('</html>'); res.end(); }) // перехват ошибки 404 app.use(function (req, res, next) { next(createError(404)); }); handler app.use(function (err, req, res, next) { res.locals.message = err.message; res.locals.error = req.app.get("env") === "development" ? err : {}; // формирование странички с ошибкой res.status(err.status || 500); res.render("error"); }); module.exports = app;
Модуль MQTT:
//подтягиваем библеотеки и переменные console.log("Script is RUN!"); const mqtt = require("mqtt"); const host = "m3.wqtt.ru"; const port = "9309"; const connectUrl = `mqtt://${host}:${port}`; const fs = require("fs"); var tempRoom; var obj; var data; //экспортируем модуль exports.mq = () => { const client = mqtt.connect(connectUrl, { clean: true, connectTimeout: 4000, username: "YOUR USERNAME", password: "YOUR PASSWORD", reconnectPeriod: 1000, }); Error.stackTraceLimit = 10; const topic = "base/state/temperature_room"; client.on("connect", () => { console.log("Connected"); client.subscribe([topic], () => { console.log(`Subscribe to topic '${topic}'`); client.on("message", (topic, payload) => { tempRoom = payload.toString(); console.log("Temp room from module", +tempRoom); data = { room: tempRoom, hot: "wait" }; data = JSON.stringify(data); fs.writeFile('/home/a0888254/domains/a0888254.xsph.ru/public_html/myapp/lib/data.json', data, (err) => { if (err) { console.error(err) return } console.log("File is writed!)"); }) }); }); }); };
Клиентская сторона
Затем я хочу использовать возможности JavaScript по записи и считыванию файлов, таким образом создав некий буферный файл, в котором текущие параметры перезаписываются при следующем обновлении. Именно отсюда я буду вытягивать AJAXом значения на клиентскую сторону. Для начала надо создать и подключить необходимый скрипт. Для этого в папке Public создадим файл app.js. Листинг можно найти в тут: /public/javascript/app.js Его задача получать данные из JSON, парсить их и выводить на страничку в режиме реального времени.
/*Когда сформировался DOM - начинается исполнение кода. Функция readFile принимает в квачестве параметргов два аргумента. А в качестве обратного вызова передает ответ на запрос.*/ document.addEventListener("DOMContentLoaded", function () { var data; var outputs = document.getElementsByTagName("output"); function readFile(file, callback) { var rawFile = new XMLHttpRequest(); rawFile.overrideMimeType("application/json"); rawFile.open("POST", file, true); rawFile.onreadystatechange = function () { if (rawFile.readyState == 4 && rawFile.status == "200") { callback(rawFile.responseText); } } rawFile.send() } function rd() { readFile("myapp/lib/data.json", function (text) { data = JSON.parse(text); outputs[0].innerHTML = '<h2 id="data" style="color=#ff6347">' + data.hot + '°C' + '</h2>'; outputs[1].innerHTML = '<h2 id="data">' + data.room + '°C' + '</h2>'; }); }; setInterval(rd, 5000) });
На клиентской стороне размещаются элементы, с которыми взаимодействует конечный пользователь. Будь то простое визуальное взаимодействие (визуальный контроль) или
непосредственные инструменты влияния на процесс. Тут речь идет о всевозможных регуляторах, кнопках, ползунках, слайдерах. В нашем случае мы просто мониторим процесс. Потому нам достаточно будет вывести схематичное отображения измеряемого параметра. и само значение. В дальнейшем, эта страничка может обрасти массой элементов управления и может даже получить звание полноценной SCADA системы. Кто знает ?
Я просто написал страничку на HTML и перевел ее в PUG для шаблонизатора. Обращайте внимание на то, какой шаблон нам надо использовать. Layot - это общий шаблон. В нем можно ничего не править. А вот index.pug - наш малец. В нем мы и работаем в контексте этого абзаца.
После стыковки серверной части и фронтенд получаем мини систему мониторинга.
Ссылка на мой репозиторий github c исходниками тут.
