Принимаем данные из Arduino в NAS Synology

Привет, друзья.
Продолжаю строить умный дом под свое оборудование. После того, как мне удалось подключить Arduino к NAS Synology, нужно научить их общаться. Для начала попробуем читать из Arduino и записывать в БД. Сделаем это на примере проекта Погодной станции. К Arduino цепляю датчики из тех что сейчас есть. Это гигрометр и термометр DHT-21/AM2301, у него в отличие от DHT-11 хороший рабочий температурный диапазон до -40 градусов. Вторым подключаю датчик давления BMP180 (BMP085), он же второй источник температуры. Таким образом, можно установить барометр дома, а гигрометр DHT-21 установить за окном. Получим температуру снаружи и внутри, влажность и давление. Схем подключения их в интернете миллион, поэтому сразу показываю результат.

DSC_3928

Быстро из стандартных примеров написал скетч для Arduino, который периодически считывает показания с датчиков и отправляет в UART.


#include <Wire.h>
#include <Adafruit_BMP085.h> // https://github.com/adafruit/Adafruit-BMP085-Library
#include <dht.h> // https://github.com/RobTillaart/Arduino/tree/master/libraries/DHTlib

dht DHT;
Adafruit_BMP085 bmp;
// Connect VCC of the BMP085 sensor to 3.3V (NOT 5.0V!)
// Connect GND to Ground
// Connect SCL to i2c clock - on '168/'328 Arduino Uno/Duemilanove/etc thats Analog 5
// Connect SDA to i2c data - on '168/'328 Arduino Uno/Duemilanove/etc thats Analog 4
#define DHT21_PIN 5

void setup()
{
Serial.begin(115200);
}

void loop()
{
// READ DATA
Serial.println("START TRANSLATION");
if (DHT.read21(DHT21_PIN) == DHTLIB_OK)
{
// DISPLAY DATA
Serial.print("DATA\tDHT21_H\t");
Serial.println(DHT.humidity, 1);
Serial.print("DATA\tDHT21_T\t");
Serial.println(DHT.temperature, 1);
}

if (bmp.begin()) {
Serial.print("DATA\tBM180_T\t");
Serial.println(bmp.readTemperature());
Serial.print("DATA\tBM180_P\t");
Serial.println(bmp.readPressure() * 7.5006e-3); // mm.hg

}
Serial.println("STOP TRANSLATION");
delay(30000);
}

В качестве протокола передачи данных принято, что каждое значение передается отдельной строкой, которая должна начинаться со слова DATA. Дальше через табуляцию следует уникальное название параметра. Я использую название датчика и букву измеряемого значения. Следом через tab само значение. Строки «START/STOP TRANSLATION» помогают отличить новые данные от старых.
Включаем на Synology протокол SSH. Подключаемся, например, при помощи PUTTY как root и пробуем.

dsgena> cat /dev/ttyUSB0
DATA DHT21_H 29.6
DATA DHT21_T 23.9
DATA BM180_T 22.20
DATA BM180_P 740.38

Теперь нужно принять эти данные на стороне сервера. Думал изначально воспользоваться PHP. Однако на Synology по-умолчанию вебсервер работает в safemode. Это хорошо для безопасности, но ему закрыт прямой доступ к любым папкам и файлам. Функция exec не работает для стандартных программ linux, а значит нельзя запустить stty для настройки COM-порта и нет доступа к самому порту. Остается BASH, а точнее его урезанная версия ash, ведь на Synology используется BusyBox. Значит особо не разгуляешься. Можно написать и скомпилировать программу на СИ, но это слишком сложно — придется где-то разворачивать среду программирования на linux, ведь для Synology это слишком тяжелая задача. Остается Perl или Python. Я выбрал второй вариант просто потому, что давно хотел попробовать его.
Для начала устанавливаем в Synology пакеты с Python 3 и Python Module.

Пакет с модулями содержит модуль serial, который позволит выполнить чтение из /dev/ttyUSB0, но сделать это сможет только пользователь root.
Эти данные нужно куда-то складывать. Просто записывать в файл бесперспективно. Будем писать в БД. В Synology есть пакет MariaDB. Ставим его. И тут выясняется, что в стандартном наборе модулей Python нет модуля для работы с mysql. Нужно ставить самому. Для облегчения процедуры ставим pip.

dsgena> ls /usr/lib/python2.7/|grep sql
sqlite3
dsgena> wget https://raw.github.com/pypa/pip/master/contrib/get-pip.py
dsgena> python get-pip.py
dsgena> python -m pip install pymysql

После всех мучений, мы наконец-то можем написать программу на python, которая сможет прочитать и записать данные из Arduino в MySQL.


import time
import serial
import pymysql
conn = pymysql.connect(host='127.0.0.1', user='test', passwd=None, db='test')
cur = conn.cursor()

ser = serial.Serial(
port='/dev/ttyUSB0',
baudrate=115200,
parity=serial.PARITY_ODD,
stopbits=serial.STOPBITS_TWO,
bytesize=serial.SEVENBITS
)

#ser.open()
ser.isOpen()
out = ''
while 1 :
time.sleep(1)
sql = ''
while ser.inWaiting() > 0:
s = ser.read(1)
if s == '\n':
spl = out.split('\t')
if spl[0] == 'DATA':
sql += "INSERT INTO test (DateT,param,val) VALUES (@DT, '"+spl[1] + "'," + spl[2] +"); "
out = ''

else:
out += s
if sql <> '':
cur.execute("SET @DT=Now(); " + sql)
conn.commit()
time.sleep(10)

Запустить программу на выполнение в фоне, причем так, чтобы можно было разорвать соединение SSH и она продолжила работу можно так:


dsgena> nohup python ttytomysql.py &

Я же добавил в файл /etc/crontab строчку и перезапустил crond:


dsgena> cat /etc/crontab
#minute hour mday month wday who command
*/30 * * * * root ps|grep -v grep| grep ttytomy.py > /dev/null || /usr/bin/python /volume1/web/arduino/ttytomy.py > /dev/null &
dsgena> synoservicecfg --restart crond

Теперь каждые 30 мин Synology сам проверяет жив ли процесс и при необходимости запускает его.

Собственно осталось лишь написать красивое отображение данных из БД в виде таблицы или графика. Я использовал библиотеку pChart на php. В результате получилась такая картинка.

Сегодня ночью обещали первый день зимы. Видно что днем давление быстро падало — приближался фронт. А с 23 часов резко поднялась влажность — это за окном пошел снег. Сегодня синоптики не подвели.
Осталось доделать наш анемометр и дополнить данные до полноценной метеостанции. Тогда можно будет уже определять какой фронт идет к нам — теплый или холодный. И не стыдно будет транслировать эти данные в проекте narodmon.ru.

Принимаем данные из Arduino в NAS Synology: 6 комментариев

  1. можно по подробнее объяснить как запускать программу на synology, в какую директорию ее сохранять

    1. Andrey, боюсь сильно подробнее не получится, т.к. само решение не очень-то простое.
      ttytomysql.py можно положить в любое место. У меня он лежит в папке веб-сервера. Главное прописать путь к этому файлу в /etc/crontab

        1. Нужно заходить через ssh админимтратором и вручную пытаться запустить. Тогда будет видно что за ошибку он выдает.

  2. при запуске программы выдает ошибку:
    line 20
    sql = »
    ^
    IndentationError: unindent does not match any outer indentation level

Добавить комментарий

Ваш e-mail не будет опубликован. Обязательные поля помечены *