Raspberry Pi Funkwetterstation 433 MHZ

      Keine Kommentare zu Raspberry Pi Funkwetterstation 433 MHZ

Einen 433MHZ Funkempfänger am Raspberry Pi angeschlossen ermöglicht den Empfang der Temperaturwerte eines Funk-Außensensors. Die Werte sollen in eine MySql Datenbank geschrieben werden.

  1. Installation von wiringpi
    sudo apt-get install wiringpi
  2. Installation von pilight auf dem Raspberry
  3. Anschluß des Funkempfängers (VCC +5V, GND, DATA)
  4. Installation von MySql auf dem Raspberry
  5. Anlegen einer Datenbank für die Wetterstation db-wetter
  6. Anpassen und Compilieren des beigefügten C-Quellcodes

Folgender Außensensor wurde verwendet:
PEARL Funk-Außensensor für Wetterstation

Der Pilight GPIO Pin (DATA) nach http://wiringx.org ist für den Funkempfänger per default GPIO 1 (das entspricht dem Pin 12 auf dem Raspberry). VCC wird an +5V angeschlossen, jedoch liegt der Signalpegel auf der DATA Leitung unterhalb von 3,3 V so daß das für den Raspi kein Problem ist.



Pilight konfiguriert den GPIO automatisch als Eingang – man kann das wie folgt kontrollieren:

pi@raspberrypi ~ $ cat /sys/class/gpio/gpio18/direction 
in

Nach der Installation von pilight kann mit dem Programm pilight-receive auf der Konsole die ID des eigenen Funk-Außensensors ermittelt werden. Diese muss dann später im Quellcode entsprechend geändert werden.

pilight-receive
{
    "message": {
        "id": 1502,
        "temperature": 3.7,
        "humidity": 22.0,
        "battery": 1
    },
    "origin": "receiver",
    "protocol": "alecto_ws1700",
    "uuid": "0000-b8-27-eb-3a53a7",
    "repeats": 2
}

Die Temperatur ist in Grad Celsius. Der Sensor unterstützt keine Luftfeuchtigkeit (Humidity liefert leider keine korrekten Werte).

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <mysql.h>

//sudo apt-get install mysql-server php5-mysql
//sudo apt-get install libmysqlclient-dev
//gcc -I/usr/include/mysql temp433.c -lmysqlclient -o temp433 -Wall

typedef struct JSON_OBJ
{
  char szId[128];
  double dTemp;
  double dHumidity;
  int iBattery;
  char szProtocol[128];
  char szOrigin[128];
} tJSON_OBJ;

#define PEARL_SENSOR_OUTDOOR     "1502"

int Write2MySql(tJSON_OBJ * pData, char *t_table);

int main(void)
{

  char szCmd[128];
  sprintf(szCmd, "/usr/bin/stdbuf -oL -eL /usr/local/bin/pilight-receive");

  char *pStr;
  char *pPos;
  FILE *pFile;

  if (system("/bin/pidof pilight-receive") == 0)
  {
    //already running
    printf("pilight-receive: already running, exit.\n");
    return 1;
  }

  pFile = popen(szCmd, "r");
  if (pFile)
  {
    char szLine[512];
    tJSON_OBJ jsonObj;

    while (fgets(szLine, sizeof(szLine), pFile))
    {
      //printf("debug: %s", szLine);
      if (szLine[0] == '{')
      {
        //new object
        memset(&jsonObj, 0x00, sizeof(jsonObj));
      }

      pStr = strstr(szLine, "\"message\":");
      if (pStr)
      {
        if (fgets(szLine, sizeof(szLine), pFile))
        {
          pStr = strstr(szLine, "\"id\": ");
          if (pStr)
          {
            pStr += 6;
            pPos = strchr(pStr, ',');
            if (pPos)
            {
              *pPos = '\0';
              strncpy(jsonObj.szId, pStr, sizeof(jsonObj.szId));
              //printf("debug ID: %s\n", pStr);

              if (strcmp(jsonObj.szId, PEARL_SENSOR_OUTDOOR) == 0)
              {
                printf("PEARL_SENSOR_OUTDOOR\n");
                if (fgets(szLine, sizeof(szLine), pFile))
                {
                  pStr = strstr(szLine, "\"temperature\": ");
                  if (pStr)
                  {
                    pStr += 15;
                    pPos = strchr(pStr, ',');
                    if (pPos)
                    {
                      *pPos = '\0';
                      //printf("debug_s: %s\n", pStr);
                      jsonObj.dTemp = atof(pStr);

                      if (fgets(szLine, sizeof(szLine), pFile))
                      {
                        pStr = strstr(szLine, "\"humidity\": ");
                        if (pStr)
                        {
                          pStr += 12;
                          pPos = strchr(pStr, ',');
                          if (pPos)
                          {
                            *pPos = '\0';

                            jsonObj.dHumidity = atof(pStr);
                            Write2MySql(&jsonObj, "t_outdoor");
                            break; //leave program
                          }
                        }
                      }
                    }
                  }
                }
              }
            }
          }
        }
      }
    }

    pclose(pFile);
  }

  printf("close program\n");
  return EXIT_SUCCESS;
}

int Write2MySql(tJSON_OBJ * pData, char *t_table)
{
  MYSQL *conn;

  /* Change me */
  char *server = "localhost";
  char *user = "wetter";
  char *password = "mypassword";
  char *database = "wetter";

  char buffer[1024];
  memset(buffer, 0x00, sizeof(buffer));
  sprintf(buffer, "INSERT INTO %s (datum,grad,luft) VALUES (NOW(),'%.3lf','%.3lf')", t_table, pData->dTemp,
          pData->dHumidity);
  printf("%s\n\n", buffer);
  
  conn = mysql_init(NULL);

  /* Connect to database */
  if (!mysql_real_connect(conn, server, user, password, database, 0, NULL, 0))
  {
    fprintf(stderr, "%s\n", mysql_error(conn));
    return 1;
  }

  printf("\n");

  if (mysql_query(conn, buffer))
  {
    printf("Error insert into ...\n");
  }
  else
  {
    printf("insert success\n");
  }

  /* close connection */
  mysql_close(conn);

  return 0;

}

Vor dem Compilieren sind die ID des Außensensors sowie die Zugangsdaten und Tabellenbezeichner für MySql im Quellcode anzupassen. MySql und das Paket libmysqlclient-dev sollte installiert sein. Ggf. noch die Buildumgebung installieren.

Das Programm bauen:

//sudo apt-get install mysql-server php5-mysql
sudo apt-get install libmysqlclient-dev
gcc -I/usr/include/mysql temp433.c -lmysqlclient -o temp433 -Wall
pi@raspberrypi ~/pilight $ ./temp433 
PEARL_SENSOR_OUTDOOR
INSERT INTO t_outdoor (datum,grad,luft) VALUES (NOW(),'3.100','22.000')
close program

Das Programm kann z.B. über einen cron job zyklisch aufgerufen werden. Nachdem es seinen Wert empfangen hat beendet es sich wieder.