Pull to refresh

Погодная станция из Arduino и Orienteer

Reading time 5 min
Views 13K
Под Новый Год ко мне приходит желание разработать что-нибудь нестандартное. В этот раз я решил начать собирать и обрабатывать погодные данные возле своего дома. И, конечно, выбрал Arduino в качестве железа, а вот в качестве хранилища и инструмента просмотра и анализа — упоминавшийся недавно на Хабрахабре конструктор бизнес-приложений Orienteer. Тем что получилось, я поделюсь в этой заметке.



Почему именно эта связка, ведь можно сделать без Arduino на голом Atmel микроконтроллере и в качестве хранилища использовать связку PHP/MySQL? Всё просто: не хотелось возится с ЛУТом, ибо лазерного принтера под рукой небыло, да и PHP порядком надоел. А самое главное — хотелось попробовать этот самый Orienteer в боевых условиях, а не тыкать кнопки в демонстрационном приложении.

Принцип работы прост: опрашиваем датчики, формируем и отправляем REST запрос в Orienteer.

В связи с небольшим количеством железа под Arduino в моем арсенале была выбрана следующая связка железа:

  1. Arduino UNO R3 (точнее ее китайский клон с CH340)
  2. Датчик температуры и влажности DHT22
  3. Ethernet шилд
  4. Соединительные провода



Аппаратная часть




Как видно схема подключения очень проста, обвязки для датчика не требуется. Берем Arduino, подключаем Ethernet шилд, подключаем датчик. Я использовал датчик DHT22, он измеряет температуру и процент влажности, вы можете использовать любой, который есть у вас под рукой.

Перейдем к коду скетча для Arduino. В самом начале все стандартно: подключаются необходимые библиотеки. В моем случае потребовались: Adafruit Unified Sensor Driver и Adafruit DHT Humidity & Temperature Unified Sensor Library, а также библиотеки для работы с Ethernet.

Код с подключением необходимых библиотек
#include <Adafruit_Sensor.h>
#include <DHT.h>
#include <DHT_U.h>

#include <SPI.h>
#include <Ethernet.h>


Далее объявляются константы для быстрого редактирования, названия сами говорят за себя, но для новичков в Arduino поясню:
  • DHTPIN — разъем Arduino к которому подключен датчик
  • DHTTYPE — тип датчика, используется библиотекой Adafruit
  • DELAY_MILLIS — интервал отправки данных, по умолчанию значение 30000UL, что означает 30 секунд
  • REST — часть URL адреса для REST протокола
  • SERVER_NAME — IP адрес или хост сервера, где запущен Orienteer
  • SERVER_PORT — порт сервера
  • AUTH_BASE64 — закодированная в BASE64 кодировке строка login:password для Basic HTTP аутентификации (в нашем случае admin:admin)
  • DEVICE_ID — идентификатор устройства сбора данных, то есть нашей Arduino, предполагается сбор с нескольких точек (например: дом/улица)

Дальше также все стандартно — инициализация датчика, Ehternet шилда. Для отправки данных по REST в Orienteer нужно подготовить JSON с информацией — класс и данные. Код для отправки запроса я вынес в отдельную функцию. Стоит обратить внимание на отправку POST запроса и базовую авторизацию, если вы недавно изучаете Arduino.

Отправка HTTP заголовков
sprintf(outBuf,"POST %s HTTP/1.1",page);
client.println(outBuf);
sprintf(outBuf,"Authorization: Basic %s", AUTH_BASE64);
client.println(outBuf);
sprintf(outBuf,"Host: %s",domainBuffer);
client.println(outBuf);
client.println(F("Connection: close\r\nContent-Type: application/x-www-form-urlencoded"));


Генерация JSON для отправки данных формируется с помощью функции sprintf():

sprintf(params,"{'@class':'Weather', 'temperature':%i, 'humidity':%i, 'device':'%s'}", temperature, humidity, DEVICE_ID);

Интервал для отправки реализован с помощью функции millis(). В случае ошибки ругаемся в последовательный интерфейс.

Orienteer и его настройка


Вот и подошли к серверной части. Запустим и настроим платформу Orienteer для получения данных и вывода графиков.

Запустить платформу можно из исходников, а можно и Docker контейнер (подробнее в официальной документации). Спасибо авторам что упаковали все это дело в контейнер, очень удобный способ доставки приложения. Для разворачивания предположим что Docker у вас установлен и есть минимальные навыки работы с ним, такие как запуск и остановка контейнера. Если это не так, то вам сюда и сюда.

Для начала скачаем свежий образ контейнера с приложением, я работал на ОС Ubuntu:

sudo docker pull orienteer/orienteer

Вы увидите следующее:



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

sudo docker run -p 8080:8080 orienteer/orienteer

Заходим на адрес localhost:8080 в браузере, входим с парой логин-пароль: admin/admin. Выберем в меню Schema → Classes → +Create для создания класса модели данных и укажем название класса — Weather. Не забудем сохранить новый класс:



Теперь создадим свойства класса. Нам нужно сохранять: температуру, процент влажности, имя устройства и время обращение устройства. На странице свойств класса (localhost:8080/class/Weather) добавим свойства:



У свойства dateTime в качестве значения по умолчанию укажем функцию sysdate() для получения текущего времени в момент прихода данных от устройства. Погрешность даже в несколько секунд не критична в нашем случае.

Готово, проверим — приходят наши данные? Все отлично, есть контакт!



Но, как мы видим — данные не в очень удобном виде нам подаются. Не беда, в Orienteer есть замечательные виджеты Pivot Table, HTML/JS и даже можно создать свою страницу для отображения, но остановимся на виджетах. Нам необходимо отображать последние пришедшие данные: температуру, процент влажности, время последнего обновления; средние показатели за дни.

Для добавления виджета перейдем Schema → Weather → Browse Class и нажмем на значок шестеренки в верхнем правом углу. Нажмем Add widget и добавим виджет Html Js Pane. Сохраним состояние виджета нажатием Save. Далее перейдем в настройки виджета по Actions → Settings, нажмем кнопку Edit.



Добавим ресурс для отображения — Weather(это значит, что данный виджет будет показываться только если мы находимся на странице просмотра объектов данного класса), укажем HTML и JS коды виджета.

HTML
<h1 id="last-temp">Update...</h1>
<h1 id="last-hum">Update...</h1>
<span id="last-datetime"></span>


JavaScript
function getWeather(){
var url = "/orientdb/query/db/sql/SELECT temperature, humidity, dateTime.format('dd.MM.yyyy HH:mm') AS dt FROM Weather ORDER BY dateTime.asLong() DESC LIMIT 1/1?rnd="+Math.random();
$.getJSON( url, {})
.done(function( data ) {
$('#last-temp').html(data.result[0].temperature + '°');
$('#last-hum').html(data.result[0].humidity+ '%');
$('#last-datetime').html(data.result[0].dt);
});
}
(function() {
getWeather();
})();


И сохраним — жмем Save.

Аналогичными действиями добавляем виджеты Pivot Table для отображения графиков. В одном для отображения средней температуры за сутки в настройках укажем SQL запрос для средней температуры:

SELECT dateTime, AVG(temperature) AS temp FROM Weather LET $day = dateTime.format('yyyy-MM-dd') GROUP BY $day

В режиме редактирования виджетов зададим конфигурацию графику:



А во втором виджете для отображения среднего процента влажности за сутки следующий SQL:

SELECT dateTime, AVG(humidity) AS hum FROM Weather LET $day = dateTime.format('yyyy-MM-dd') GROUP BY $day

Но в конфигурации графика укажем значение hum с результата SQL запроса:



И в итоге у нас получилась отличная система для сбора и отображения погодных данных.

Длинный скриншот


В планах:

  • Добавить дополнительные датчики: давления, CO2, уровня освещенности
  • Добавить часы реального времени(корректная реализация, когда у нас время считывания, а не время получения данных)
  • Предварительное кеширование на SD карту памяти для выгрузки среза данных
  • Вывод на дисплей погодных данных и сообщений об ошибках датчиков или проблем со связью
    настройка виджета

Все обновления будут на GitHub. А я тем временем полез на Aliexpress заказывать железо для совершенствования своей системы. Хочется еще попробовать Orienteer в качестве backend приложения для AngularJS или Android приложения, но это тема отдельной статьи.
Tags:
Hubs:
+19
Comments 14
Comments Comments 14

Articles