Принимаем данные из 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: 12 комментариев

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

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

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

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

    1. При копировании с сайта у вас кавычки изменились. Есть разница между
      » и "

  3. Hi there,

    I really like this project of yours, but did you ever try to send serial data from Synology to Arduino?

    Kind regards,
    Viktor

      1. Hi gena,

        Thank you for your fast feedback! 😉

        Is that example of yours in Python language or bash command?

        Can you maybe tell me if you know, how I can send the CPU usage, RAM usage and HDD space from Python?

        Can you give me some information from where I can start?

        Kind regards,
        Viktor

          1. Thank you for the link!

            Also I would like to tell you that your post was the ONLY ONE that I had found on the internet regarding Arduino and Synology interaction!

            So, thank you again for this great project! <3 😉

            Kind regards,
            Viktor

Добавить комментарий для Andrey Отменить ответ

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