Мониторинг температуры и влажности с помощью Raspberry Pi

Задача

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

Аппаратные средства

Для контроля температуры и влажности с помощью Raspberry Pi нам понадобится датчик DHT11.
DHT11
Его не сложно найти и купить в Москве.
Подключаем его как на фото:
SDIM0040
Подробнее описано на Хабре http://habrahabr.ru/post/167459/

Датчик не защищен от коротких замыканий, потому есть смысл для него изготовить кожух. Для этого отрежьте немного термоусаживоемой трубки, прорежьте в ней отверстия для циркуляции воздуха и наденьте на датчик. После с помощью фена или зажигалки нагрейте края трубки в нужных местах. Получится вот такая конструкция:
SDIM0041

Программные средства

В качестве операционной системы использовался Raspbian на базе Debian Linux.
http://www.raspberrypi.org/downloads

Теперь пришла пора скомпилировать программу для мониторинга.
Если вам нужно просто мониторинг без каких либо дополнительных действий, то исходный код находится тут:
http://www.rpiblog.com/2012/11/interfacing-temperature-and-humidity.html

Оповещение

В качестве оповещения применяется Jabber.

Отключение

Для отключения применим rsh.

Для оповещения и отключения серверов пришлось немного доработать программу и написать дополнительные скрипты.
Делаем:

Программа

su
cd
mkdir sensor
cd sensor/
vi temp_rh_sensor.c

И вводим

    #include <wiringpi .h>  
   #include <stdio .h>  
   #include <stdlib .h>  
   #include <stdint .h>  
   #define MAX_TIME 85  
   #define DHT11PIN 7  


    int hottemp=24;
    int maxtemp=26;

    /*int hottemp=21;*/
    /*int maxtemp=22;*/

    int wethumid=60;
    int maxhumid=75;



    int dht11_val[5]={0,0,0,0,0};  
     
    void dht11_read_val()  
    {  
      uint8_t lststate=HIGH;  
      uint8_t counter=0;  
      uint8_t j=0,i;  
      float farenheit;  
      for(i=0;i&lt;5;i++)  
         dht11_val[i]=0;  
      pinMode(DHT11PIN,OUTPUT);  
      digitalWrite(DHT11PIN,LOW);  
      delay(18);  
      /*18*/
      digitalWrite(DHT11PIN,HIGH);  
      delayMicroseconds(40);  
      /*40*/
      pinMode(DHT11PIN,INPUT);  
      for(i=0;i<max_time ;i++)  
      {  
        counter=0;  
        while(digitalRead(DHT11PIN)==lststate){  
          counter++;  
          delayMicroseconds(1);  
          if(counter==255)  
            break;  
        }  
        lststate=digitalRead(DHT11PIN);  
        if(counter==255)  
           break;  
        // top 3 transistions are ignored  
        if((i>=4)&&(i%2==0)){  
          dht11_val[j/8]< <=1;  
          if(counter>16)  
            dht11_val[j/8]|=1;  
          j++;  
        }  
      }  
      // verify cheksum and print the verified data  
      if((j>=40)&&(dht11_val[4]==((dht11_val[0]+dht11_val[1]+dht11_val[2]+dht11_val[3])& 0xFF)))  
      {  
        farenheit=dht11_val[2]*9./5.+32;  
    printf("Влажность = %d.%d%% Температура = %d.%dºC (%.1fºF)\n",dht11_val[0],dht11_val[1],dht11_val[2],dht11_val[3],farenheit);



        /*Процедура отключения по температуре */
    if (dht11_val[2]>maxtemp)
    {
    printf("Внимание! Температура критическая! больше %dºC градусов! Составляет:%dºC! Сервера отключаются!!! \n",maxtemp,dht11_val[2]);
           char strjabber[254];

           sprintf(strjabber, "echo 'Внимание! Температура критическая! больше %dºC. Составляет:%dºC! Сервера отключаются!!!' | sergey",maxtemp,dht11_val[2]);
                   system(strjabber);
                   sleep(60);

   

           system("/usr/local/bin/power-off-all.sh");

    }
        /*Процедура оповещения по температуре*/
       if (dht11_val[2]>hottemp)
    {
        printf("Внимание! Температура больше %dºC градусов! Составляет:%dºC \n",hottemp,dht11_val[2]);
           char strjabber[254];

        sprintf(strjabber, "echo 'В серверной температура выше нормы: %dºC!!! Сейчас: %dºC. При достижении более %dºC сервера автоматически отключатся!!!' | sergey",hottemp,dht11_val[2],maxtemp);
        system(strjabber);
        sleep(60);


    }




        /*Процедура отключения по влажности*/
    if (dht11_val[0]>maxhumid)
    {
    printf("Внимание! Влажность критическая! больше %d%% и составляет:%d,%d%% Сервера отключаются!!! \n",maxhumid,dht11_val[0],dht11_val[1]);
           char strjabber[254];

          sprintf(strjabber, "echo 'Внимание! Влажность критическая! больше %d%%. Составляет:%d%! Сервера отключаются!!!' | sergey",maxhumid,dht11_val[0]);
                   system(strjabber);
                   sleep(20);

   

        system("/usr/local/bin/power-off-all.sh");

    }
        /*Процедура оповещения по влажности*/
    if (dht11_val[0]>wethumid)
    {
        printf("Влажность больше %d% и Составляет:%d.%d%% При привышения %d% сервера будут отключены! \n",wethumid,dht11_val[0],dht11_val[1],maxhumid);
          char strjabber[254];

        sprintf(strjabber, "echo 'В серверной влажность выше нормы: %d%!!! Сейчас: %d,%d%%. При достижении более %d% сервера автоматически отключатся!!!' | sergey",wethumid,dht11_val[0],dht11_val[1],maxhumid);
        system(strjabber);
        sleep(60);


    }







      }  
      /*else  */
        /*printf("Invalid Data!!\n");  */
    }  
     
    int main(void)  
    {  
      printf("\n\n        Контроль температуры и влажности\n-----------------------------------------------\n");  
      if(wiringPiSetup()==-1)  
        exit(1);  
      while(1)  
      {  
         dht11_read_val();  
         delay(3000);  
      }  
      return 0;  
    }

Программа не выглядит элегантно. Я не программист. Наверно тут надо по чаще пользоваться циклом 🙂 Если кто может помочь, буду благодарен.

Теперь о деталях программы:
Вот такой текст позводит составить строчку для отсылки в jabber нужных вам сообщений:

sprintf(strjabber, "echo 'В серверной температура выше нормы: %dºC!!! Сейчас: %dºC. При достижении более %dºC сервера автоматически отключатся!!!' | sergey",hottemp,dht11_val[2],maxtemp);
        system(strjabber);
        sleep(2);

Тут «sergey» это название скрипта, который в jabber посылает сообщение Сергею.
ВОт как он выглядит:

vi /usr/local/bin/sergey

#!/usr/bin/perl
#
#               Require modules:
#                       Digest::SHA1
#                       Unicode::String
#                       XML::Stream
#                       Net::Jabber
#
#       For more examples: look 'Net-Jabber-*.tar.gz/Net-Jabber-*/examples/*.pl'
#
use utf8;
binmode(STDIN, ':utf8');
binmode(STDOUT, ':utf8');

use Net::Jabber qw(Client);
use strict;

my $server = "oes.local.net";
my $port = "5222";
my $username = "admin";
my $password = "iddqd";

my $resource = "BEREG-SEND";
my $component = "admin\@oes.msk.local.net";




my $subject = "Контроль температуры и влажности в серверной";


#my $body="test";
my $body=<stdin>;

#############################################################

my $Client = new Net::Jabber::Client;

#       uncomment next line for recieve answer
#$Client->SetCallBacks(message=>\&messageCB);

my $status = $Client->Connect(hostname=>$server,
                port=>$port);
if (!(defined($status))) {
        print "ERROR:  Jabber server $server is not answering.\n";
        print "        ($!)\n";
        exit(0);
}

print "Connected...\n";
my @result = $Client->AuthSend(username=>$username,
                        password=>$password,
                        resource=>$resource);
if ($result[0] ne "ok") {
        print "ERROR: $result[0] $result[1]\n";
}

print "Logged in...\n";
$Client->MessageSend(
    to=>$component,
    subject=>$subject,
        body=>$body);

#       uncomment next line for recieve answer
#$Client->Process();

$Client->Disconnect();

sub messageCB {
        my $sid = shift;
        my $message = shift;

        print "The body of the message should read:\n";
        print "  (THIS IS A TEST... A SUCCESSFUL TEST...)\n";
        print "\n";
        print "Recvd: ",$message->GetBody(),"\n";
}
chmod +x /usr/local/bin/sergey

По образу и подобию делаются все остальные скрипты для отсылки сообщений пользователям.
На самом деле, в этот скрипт можно поместить не только отсылку в Jabber, но и winpopup, почту и т д.

Теперь скрипт для отключения серверов.

vi /usr/local/bin/power-off-all.sh
#!/bin/bash

#command="rm /var/log/TestPowerOf.txt"
#command="touch /var/log/TestPowerOf.txt"
command="poweroff -p"

echo "Отключается сервер bereg-db"
rsh root@192.168.0.7 $command ||  echo "Не удалось отключить сервер db" | /usr/local/bin/sergey

echo "Отключается сервер bereg-db-standby"
rsh root@192.168.0.6 $command ||  echo "Не удалось отключить сервер db-standby" | /usr/local/bin/sergey
chmod +x /usr/local/bin/power-off-all.sh

Для удобства редактирования и последующей компиляции напишем еще скриптик:

vi /usr/local/bin/compillsensor.sh
#!/bin/bash
#gcc -o mysensor temp_rh_sensor.c -L/usr/local/lib -lwiringPi && ./mysensor
gcc -o /root/sensor/mysensor /root/sensor/temp_rh_sensor.c -L/usr/local/lib -lwiringPi &&  cp /root/sensor/mysensor /usr/local/bin/mysensor
if [ -f /usr/local/bin/mysensor ];then
        /usr/local/bin/mysensor
else
        echo "/usr/local/bin/mysensor Не собран или стерт."
fi

И запускаем компиляцию
/usr/local/bin/compillsensor.sh

Для автоматического запуска

vi /etc/rc.local
/etc/init.d/console-setup start
LANG="ru_RU.UTF-8" screen /usr/local/bin/mysensor || echo "Не запустился в скрине мониторинг температуры" | sergey

И как всегда, замените «sergey» на ваш скрипт отсылки сообщений.
Учитывая, что программа запускается в screen, вы можете подключиться в прибору по ssh и вывести на свой дисплей мониторинг.

screen -D
screen -r
Влажность = 34.0% Температура = 21.0ºC (69.8ºF)
Влажность = 34.0% Температура = 22.0ºC (71.6ºF)
Влажность = 34.0% Температура = 22.0ºC (71.6ºF)
Влажность = 34.0% Температура = 22.0ºC (71.6ºF)
Влажность = 34.0% Температура = 21.0ºC (69.8ºF)
Влажность = 34.0% Температура = 21.0ºC (69.8ºF)
Влажность = 34.0% Температура = 22.0ºC (71.6ºF)
Влажность = 34.0% Температура = 21.0ºC (69.8ºF)
Влажность = 34.0% Температура = 21.0ºC (69.8ºF)
Влажность = 34.0% Температура = 21.0ºC (69.8ºF)
Влажность = 34.0% Температура = 21.0ºC (69.8ºF)

Для выхода из мониторинга нажмите Ctrl-a-d или перезагрузите устройство коммандой reboot.

Запись опубликована в рубрике Linux, Raspberry. Добавьте в закладки постоянную ссылку.

4 комментария на «Мониторинг температуры и влажности с помощью Raspberry Pi»

  1. Алексей говорит:

    Добрый день!

    Мне необходимо 1 раз в день получать информацию о валжности и температуре в пчелозимовнике. т.е. устройство которое бы измеряло скидывало мне эти данные на телефоне в виде смс. Или чтобы устройтво информировало меня если температура поднимется выше +4С или опустится ниже 0С. Можете посоветовать что-то в этом роде или даже сделать? Сколько это стоит?

    • Ярослав говорит:

      К usb порту raspberry pi можно подключить обычный usb модем и перенаправлять вывод указанной выше программы в виде смс на твой номер.
      raspberry 2 тыс. руб., модем 300 руб., датчик даже не знаю сколько стоит 100-200 рублей?

      в 2,5 — 3 тыс. рублей уложишься.

  2. Павел говорит:

    Хотел бы побеседовать» со спецами по этой теме !
    напишите? пожалуйста, мне письмо.. acd23ГАВmail.ru

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

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

Анти-спам: выполните заданиеWordPress CAPTCHA