Домашняя метеостанция. Часть 2

Важно понимать, что API, о котором пойдёт речь ниже — это компиляция нескольких курсов найденных мной в интернете, постоянного чтения документации и регулярных консультаций неравнодушных людей. В текущем виде исходный код не претендует на оригинальность.

💫 Вдохновлено мечтой.

Название

В первой части я говорил, что разделил процесс создания метеостанции на три этапа. По сути, это три отдельных проекта, которые теперь объединены под одним общим названием — Zarya.

Zarya Meteostation — это метеостанция на базе Iskra JS, которая собирает погодные данные и передаёт их на сервер. Подробнее про неё написано в первой части цикла.

Zarya API — это API, который принимает погодные данные от Zarya Meteostation. В данном материале речь пойдёт о Zarya API.

Zarya Assistant — это Telegram-бот, который будет использоваться в качестве интерфейса для получения погодных данных из Zarya API. На данный момент проект разрабатывается и третья часть цикла будет посвящена Zarya Assistant.

Кажется, это звучит лучше, чем безликая «домашняя метеостанция».

Общее описание API

Zarya API — это небольшой API, написанный на Node JS, позволяющий принимать данные с Zarya Meteostation (метеостанция на основе Iskra JS) и записывать их в MongoDB. Обладает методами GET (получение), POST (добавление), PUT (изменение) и DELETE (удаление). Имеет Basic-авторизацию через HTTP.

Как работает API

Примерный принцип работы проекта, я понимал ещё в декабре 2017-го. Но необходимый уровень знаний для его реализации у меня появился только в 2019-м. Запись из личного дневника.

Клиент (в моём случае, это Iskra JS) по специальному URL отправляет запрос на сервер. Чтобы сервер принял запрос, на нём нужно авторизоваться. В противном случае, сервер отклонит его.

Затем, происходит проверка передаваемых данных с помощью схемы валидации. Если с данными всё хорошо, они записываются в базу.

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

Например, чтобы Zarya Assistant получил текущую погоду, нужно выполнить запрос и вернуть данные.

Это несколько упрощённое описание работы API. Можно самостоятельно ознакомиться с репозиторием на GitHub и вникнуть в код.

Stack технологий

Сервер

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

Хостинг я выбрал давно — это Digital Ocean. В качестве ОС для сервера я выбирал между Debian и Ubuntu. На первый взгляд, особой разницы нет. После небольшого исследования, я выяснил, что Debian более стабильный, потому и выбрал его.

За Node JS на сервере отвечает NVM (Node Version Manager) — это небольшой скрипт, который позволяет легко контролировать версии Node JS.

Следить за процессами Node JS мне помогает менеджер процессов pm2. Он может автоматически перезапускать приложения, если они прекращают работу.

Чтобы мой API был доступен не только по IP-адресу, но и по URL, нужен веб-сервер и домен. Домен у меня есть, а веб-сервера не было. Сначала я установил и настроил Nginx. Выбрал его только из-за того, что он наиболее популярный. Но затем, по совету моего бывшего коллеги Саши Купоросова, я обратил внимание на Caddy.

Caddy оказалось гораздо легче настраивать, чем Nginx. К тому же он автоматически запрашивает SSL-сертификаты для доменов через Let’s Encrypt и поддерживает HTTP 2. Nginx тоже может автоматически получать сертификаты и поддерживает HTTP 2, но для этого нужно устанавливать Certbot, настраивать его через Cron, и конфигурировать каждый файл каждого сайта. В Caddy один конфигурационный файл на всё.

В качестве защиты работает UFW (Uncomplicated Firewall) — это довольно простой firewall, но обращаться с ним нужно аккуратно. Иначе можно остаться без доступа по SSH.

Мой комплект Raspberry Pi 3 Model B+, который несколько раз спасал меня от потери доступа по SSH к основному серверу

У меня почти не было опыта взаимодействия с UNIX-системами (кроме macOS) и чтобы потренироваться, я купил себе Raspberry Pi 3 Model B+. Мой основной страх в тот момент — это то, что я что-нибудь сделаю не так и потеряю удалённый доступ по SSH. А если я всё испытаю локально на Raspberry Pi и что-то пойдёт не так, то я всегда смогу всё исправить. И сейчас я могу уверенно сказать, что это было стратегически верным решением. После того как я несколько раз терял доступ по SSH, мне удалось избежать допущенных ошибок на основном сервере.

API

API построен на ряде библиотек, каждая из которых отвечает за свою функцию.

Express JS — фреймворк для написания веб-приложений. С его помощью API создаёт веб-сервер и маршрутизацию.

Express Basic Auth — простая библиотека для Express JS, которая позволяет производить авторизацию в приложении по HTTP. Это не самый надёжный вариант для авторизации, но пока и такого хватит.

Body Parser — библиотека для парсинга запросов.

MongoDB — не реляционная (NoSQL) база данных. В ней хранятся все данные, которые получает метеостанция.

Основное отличие от реляционных баз данных в том, что MongoDB хранит в себе BSON — это JSON-подобные документы. В то время как реляционные базы используют табличный тип хранения данных.

Возможно, позже MongoDB будет заменена на time series базу данных.

MongoDB Driver — официальная библиотека MongoDB для Node JS. Используется для подключения API к базе данных.

Mongoose — библиотека для MongoDB, которая позволяет API производить валидацию получаемых данных по заранее заданной схеме.

Развитие

На данный момент этой функциональности API хватает для того, чтобы доделать до конца MVP. Но у меня уже есть backlog задач, который поможет сделать проект более гибким в будущем. Вы можете написать мне (@boboshko), если хотите присоединиться к разработке.

Благодарности

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

Я хочу поблагодарить: Сашу Купоросова, Вову Артамонова, Влада Самойлова, Стаса Понаморёва, Вадима Репина, Диму Гуденкова и Женю Кочеткова.

Отдельно хочу отметить своих товарищей Сашу Катина (помог с переводом репозитория) и Илью Лыткина (он помогал с документацией).

Если я кого-то упустил, напишите мне и я всё исправлю.


Если у вас остались вопросы, вы можете их задать в чате канала: @codeque.

Подписывайтесь на мой канал, Twitter и Instagram.