Initial project Import

git-svn-id: file:///home/jan/tmp/wetterstation/trunk@2 dd492736-c11a-0410-ad51-8c26713eaf7f
This commit is contained in:
losinshi 2006-08-11 17:48:22 +00:00
parent 4215d43ce9
commit df47982571
14 changed files with 1976 additions and 0 deletions

339
seriell/COPYING Normal file
View File

@ -0,0 +1,339 @@
GNU GENERAL PUBLIC LICENSE
Version 2, June 1991
Copyright (C) 1989, 1991 Free Software Foundation, Inc.
675 Mass Ave, Cambridge, MA 02139, USA
Everyone is permitted to copy and distribute verbatim copies
of this license document, but changing it is not allowed.
Preamble
The licenses for most software are designed to take away your
freedom to share and change it. By contrast, the GNU General Public
License is intended to guarantee your freedom to share and change free
software--to make sure the software is free for all its users. This
General Public License applies to most of the Free Software
Foundation's software and to any other program whose authors commit to
using it. (Some other Free Software Foundation software is covered by
the GNU Library General Public License instead.) You can apply it to
your programs, too.
When we speak of free software, we are referring to freedom, not
price. Our General Public Licenses are designed to make sure that you
have the freedom to distribute copies of free software (and charge for
this service if you wish), that you receive source code or can get it
if you want it, that you can change the software or use pieces of it
in new free programs; and that you know you can do these things.
To protect your rights, we need to make restrictions that forbid
anyone to deny you these rights or to ask you to surrender the rights.
These restrictions translate to certain responsibilities for you if you
distribute copies of the software, or if you modify it.
For example, if you distribute copies of such a program, whether
gratis or for a fee, you must give the recipients all the rights that
you have. You must make sure that they, too, receive or can get the
source code. And you must show them these terms so they know their
rights.
We protect your rights with two steps: (1) copyright the software, and
(2) offer you this license which gives you legal permission to copy,
distribute and/or modify the software.
Also, for each author's protection and ours, we want to make certain
that everyone understands that there is no warranty for this free
software. If the software is modified by someone else and passed on, we
want its recipients to know that what they have is not the original, so
that any problems introduced by others will not reflect on the original
authors' reputations.
Finally, any free program is threatened constantly by software
patents. We wish to avoid the danger that redistributors of a free
program will individually obtain patent licenses, in effect making the
program proprietary. To prevent this, we have made it clear that any
patent must be licensed for everyone's free use or not licensed at all.
The precise terms and conditions for copying, distribution and
modification follow.
GNU GENERAL PUBLIC LICENSE
TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
0. This License applies to any program or other work which contains
a notice placed by the copyright holder saying it may be distributed
under the terms of this General Public License. The "Program", below,
refers to any such program or work, and a "work based on the Program"
means either the Program or any derivative work under copyright law:
that is to say, a work containing the Program or a portion of it,
either verbatim or with modifications and/or translated into another
language. (Hereinafter, translation is included without limitation in
the term "modification".) Each licensee is addressed as "you".
Activities other than copying, distribution and modification are not
covered by this License; they are outside its scope. The act of
running the Program is not restricted, and the output from the Program
is covered only if its contents constitute a work based on the
Program (independent of having been made by running the Program).
Whether that is true depends on what the Program does.
1. You may copy and distribute verbatim copies of the Program's
source code as you receive it, in any medium, provided that you
conspicuously and appropriately publish on each copy an appropriate
copyright notice and disclaimer of warranty; keep intact all the
notices that refer to this License and to the absence of any warranty;
and give any other recipients of the Program a copy of this License
along with the Program.
You may charge a fee for the physical act of transferring a copy, and
you may at your option offer warranty protection in exchange for a fee.
2. You may modify your copy or copies of the Program or any portion
of it, thus forming a work based on the Program, and copy and
distribute such modifications or work under the terms of Section 1
above, provided that you also meet all of these conditions:
a) You must cause the modified files to carry prominent notices
stating that you changed the files and the date of any change.
b) You must cause any work that you distribute or publish, that in
whole or in part contains or is derived from the Program or any
part thereof, to be licensed as a whole at no charge to all third
parties under the terms of this License.
c) If the modified program normally reads commands interactively
when run, you must cause it, when started running for such
interactive use in the most ordinary way, to print or display an
announcement including an appropriate copyright notice and a
notice that there is no warranty (or else, saying that you provide
a warranty) and that users may redistribute the program under
these conditions, and telling the user how to view a copy of this
License. (Exception: if the Program itself is interactive but
does not normally print such an announcement, your work based on
the Program is not required to print an announcement.)
These requirements apply to the modified work as a whole. If
identifiable sections of that work are not derived from the Program,
and can be reasonably considered independent and separate works in
themselves, then this License, and its terms, do not apply to those
sections when you distribute them as separate works. But when you
distribute the same sections as part of a whole which is a work based
on the Program, the distribution of the whole must be on the terms of
this License, whose permissions for other licensees extend to the
entire whole, and thus to each and every part regardless of who wrote it.
Thus, it is not the intent of this section to claim rights or contest
your rights to work written entirely by you; rather, the intent is to
exercise the right to control the distribution of derivative or
collective works based on the Program.
In addition, mere aggregation of another work not based on the Program
with the Program (or with a work based on the Program) on a volume of
a storage or distribution medium does not bring the other work under
the scope of this License.
3. You may copy and distribute the Program (or a work based on it,
under Section 2) in object code or executable form under the terms of
Sections 1 and 2 above provided that you also do one of the following:
a) Accompany it with the complete corresponding machine-readable
source code, which must be distributed under the terms of Sections
1 and 2 above on a medium customarily used for software interchange; or,
b) Accompany it with a written offer, valid for at least three
years, to give any third party, for a charge no more than your
cost of physically performing source distribution, a complete
machine-readable copy of the corresponding source code, to be
distributed under the terms of Sections 1 and 2 above on a medium
customarily used for software interchange; or,
c) Accompany it with the information you received as to the offer
to distribute corresponding source code. (This alternative is
allowed only for noncommercial distribution and only if you
received the program in object code or executable form with such
an offer, in accord with Subsection b above.)
The source code for a work means the preferred form of the work for
making modifications to it. For an executable work, complete source
code means all the source code for all modules it contains, plus any
associated interface definition files, plus the scripts used to
control compilation and installation of the executable. However, as a
special exception, the source code distributed need not include
anything that is normally distributed (in either source or binary
form) with the major components (compiler, kernel, and so on) of the
operating system on which the executable runs, unless that component
itself accompanies the executable.
If distribution of executable or object code is made by offering
access to copy from a designated place, then offering equivalent
access to copy the source code from the same place counts as
distribution of the source code, even though third parties are not
compelled to copy the source along with the object code.
4. You may not copy, modify, sublicense, or distribute the Program
except as expressly provided under this License. Any attempt
otherwise to copy, modify, sublicense or distribute the Program is
void, and will automatically terminate your rights under this License.
However, parties who have received copies, or rights, from you under
this License will not have their licenses terminated so long as such
parties remain in full compliance.
5. You are not required to accept this License, since you have not
signed it. However, nothing else grants you permission to modify or
distribute the Program or its derivative works. These actions are
prohibited by law if you do not accept this License. Therefore, by
modifying or distributing the Program (or any work based on the
Program), you indicate your acceptance of this License to do so, and
all its terms and conditions for copying, distributing or modifying
the Program or works based on it.
6. Each time you redistribute the Program (or any work based on the
Program), the recipient automatically receives a license from the
original licensor to copy, distribute or modify the Program subject to
these terms and conditions. You may not impose any further
restrictions on the recipients' exercise of the rights granted herein.
You are not responsible for enforcing compliance by third parties to
this License.
7. If, as a consequence of a court judgment or allegation of patent
infringement or for any other reason (not limited to patent issues),
conditions are imposed on you (whether by court order, agreement or
otherwise) that contradict the conditions of this License, they do not
excuse you from the conditions of this License. If you cannot
distribute so as to satisfy simultaneously your obligations under this
License and any other pertinent obligations, then as a consequence you
may not distribute the Program at all. For example, if a patent
license would not permit royalty-free redistribution of the Program by
all those who receive copies directly or indirectly through you, then
the only way you could satisfy both it and this License would be to
refrain entirely from distribution of the Program.
If any portion of this section is held invalid or unenforceable under
any particular circumstance, the balance of the section is intended to
apply and the section as a whole is intended to apply in other
circumstances.
It is not the purpose of this section to induce you to infringe any
patents or other property right claims or to contest validity of any
such claims; this section has the sole purpose of protecting the
integrity of the free software distribution system, which is
implemented by public license practices. Many people have made
generous contributions to the wide range of software distributed
through that system in reliance on consistent application of that
system; it is up to the author/donor to decide if he or she is willing
to distribute software through any other system and a licensee cannot
impose that choice.
This section is intended to make thoroughly clear what is believed to
be a consequence of the rest of this License.
8. If the distribution and/or use of the Program is restricted in
certain countries either by patents or by copyrighted interfaces, the
original copyright holder who places the Program under this License
may add an explicit geographical distribution limitation excluding
those countries, so that distribution is permitted only in or among
countries not thus excluded. In such case, this License incorporates
the limitation as if written in the body of this License.
9. The Free Software Foundation may publish revised and/or new versions
of the General Public License from time to time. Such new versions will
be similar in spirit to the present version, but may differ in detail to
address new problems or concerns.
Each version is given a distinguishing version number. If the Program
specifies a version number of this License which applies to it and "any
later version", you have the option of following the terms and conditions
either of that version or of any later version published by the Free
Software Foundation. If the Program does not specify a version number of
this License, you may choose any version ever published by the Free Software
Foundation.
10. If you wish to incorporate parts of the Program into other free
programs whose distribution conditions are different, write to the author
to ask for permission. For software which is copyrighted by the Free
Software Foundation, write to the Free Software Foundation; we sometimes
make exceptions for this. Our decision will be guided by the two goals
of preserving the free status of all derivatives of our free software and
of promoting the sharing and reuse of software generally.
NO WARRANTY
11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN
OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS
TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE
PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
REPAIR OR CORRECTION.
12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
POSSIBILITY OF SUCH DAMAGES.
END OF TERMS AND CONDITIONS
Appendix: How to Apply These Terms to Your New Programs
If you develop a new program, and you want it to be of the greatest
possible use to the public, the best way to achieve this is to make it
free software which everyone can redistribute and change under these terms.
To do so, attach the following notices to the program. It is safest
to attach them to the start of each source file to most effectively
convey the exclusion of warranty; and each file should have at least
the "copyright" line and a pointer to where the full notice is found.
<one line to give the program's name and a brief idea of what it does.>
Copyright (C) 19yy <name of author>
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
Also add information on how to contact you by electronic and paper mail.
If the program is interactive, make it output a short notice like this
when it starts in an interactive mode:
Gnomovision version 69, Copyright (C) 19yy name of author
Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
This is free software, and you are welcome to redistribute it
under certain conditions; type `show c' for details.
The hypothetical commands `show w' and `show c' should show the appropriate
parts of the General Public License. Of course, the commands you use may
be called something other than `show w' and `show c'; they could even be
mouse-clicks or menu items--whatever suits your program.
You should also get your employer (if you work as a programmer) or your
school, if any, to sign a "copyright disclaimer" for the program, if
necessary. Here is a sample; alter the names:
Yoyodyne, Inc., hereby disclaims all copyright interest in the program
`Gnomovision' (which makes passes at compilers) written by James Hacker.
<signature of Ty Coon>, 1 April 1989
Ty Coon, President of Vice
This General Public License does not permit incorporating your program into
proprietary programs. If your program is a subroutine library, you may
consider it more useful to permit linking proprietary applications with the
library. If this is what you want to do, use the GNU Library General
Public License instead of this License.

41
seriell/Makefile Normal file
View File

@ -0,0 +1,41 @@
CC = gcc
LD = gcc
RM = rm
DEBUG = -DDEBUG
FLAGS =
binary:
#make clean
# Compile
$(CC) $(FLAGS) -o main.o -c main.c
$(CC) $(FLAGS) -o input.o -c input.c
$(CC) $(FLAGS) -o process.o -c process.c
$(CC) $(FLAGS) -I/usr/include/postgresql -o write.o -c write.c
$(CC) $(FLAGS) -o config.o -c config.c
# Link
$(LD) $(FLAGS) -L/usr/lib/pgsql -lpq -o weatherdeamon main.o input.o process.o write.o config.o
debug:
#make clean
# Compile
$(CC) -DDEBUG -o main.o -c main.c
$(CC) -DDEBUG -o input.o -c input.c
$(CC) -DDEBUG -o process.o -c process.c
$(CC) -DDEBUG -I/usr/include/postgresql -o write.o -c write.c
$(CC) -DDEBUG -o config.o -c config.c
# Link
$(LD) -DDEBUG -L/usr/lib/pgsql -lpq -o weatherdeamon main.o input.o process.o write.o config.o
partclean:
#remove *.o
$(RM) main.o input.o process.o
clean:
#remove all output
$(RM) main.o input.o process.o write.o config.o weatherdeamon
# Die postgres-pfade bekommt man mit pg_config raus!

179
seriell/config.c Normal file
View File

@ -0,0 +1,179 @@
/*
weatherdeamon -- Weather Data Capture Program for the
'ELV-PC-Wettersensor-Empfänger'
config.c -- Part of the weatherdeamon
Copyright (C) 2006 Jan Losinski
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
$Id: process.c v 1.00 11 Aug 2006 losinski $
*/
#include <string.h>
#include <stdlib.h>
#include <stdio.h>
#include "config.h"
#include "definitions.h"
#include "main.h"
static int read_str(const char *, void *);
static read_log_data_flag(const char *, void *);
static read_log_error_flag(const char *, void *);
static read_foreground_flag(const char *, void *);
static read_verbose_flag(const char *, void *);
static int flag_handler(int *, int , const char *);
/* Zuordnung zwischen Schlüsselwörtern in der Config, Der Funktion, die diese auswertet
* und dem eld in der Options-Struktur */
static const struct config_keyword keywords[] = {
/* keyword handler variable address default */
{"interface", read_str, &(global_opts.device), DEFAULT_SERIAL_PORT},
{"log_data", read_log_data_flag, &(global_opts.flags), "no"},
{"log_error", read_log_error_flag, &(global_opts.flags), "no"},
{"data_file", read_str, &(global_opts.data_log), DEFAULT_DATA_FILE},
{"error_file", read_str, &(global_opts.error_log), DEFAULT_ERROR_FILE},
{"foreground", read_foreground_flag, &(global_opts.flags), "no"},
{"verbose", read_verbose_flag, &(global_opts.flags), "no"},
{"pg_host", read_str, &(global_opts.pg_host), DEFAULT_PG_HOST},
{"pg_user", read_str, &(global_opts.pg_user), DEFAULT_PG_USER},
{"pg_pass", read_str, &(global_opts.pg_pass), DEFAULT_PG_PASS},
{"pg_database", read_str, &(global_opts.pg_database), DEFAULT_PG_DATABASE},
{"", NULL, NULL, ""}
};
/* Liest eine Option (line) als String und speichert diese in
* dem entsprechendem Feld der Optionen-Struktur (arg) */
static int read_str(const char *line, void *arg){
char **dest = arg;
if (*dest) free(*dest);
*dest = strdup(line);
return 1;
}
/* Die 4 Funktionen reichen jeweils nur die Daten an den
* flag_handler durch und teilen diesem noch das Flag
* mit, was er setzen soll (oder nicht) */
static read_log_data_flag(const char *line, void *arg){
return flag_handler(arg, LOG_DATA_FLAG, line);
}
static read_log_error_flag(const char *line, void *arg){
return flag_handler(arg, LOG_ERROR_FLAG, line);
}
static read_foreground_flag(const char *line, void *arg){
return flag_handler(arg, FOREGROUND_FLAG, line);
}
static read_verbose_flag(const char *line, void *arg){
return flag_handler(arg, VERBOSE_FLAG, line);
}
/* Setzt Flags wenn der String gleich 'yes' ist */
static int flag_handler(int *dest, int flag, const char *line){
if (strcmp("yes", line) == 0){
*dest |= flag;
} else {
*dest &= ~flag;
}
return 1;
}
/* Liest und verarbeitet die Config-File
* der Integer reset gibt an, ob zu begin defaultwerte
* gesetzt werden sollen oder nicht */
int read_config(const char *file, int reset){
FILE *in; /* File-Handler */
char buffer[CONFIG_BUFFERSIZE], *token, *line; /* Puffer zum lesen der config-file (imer 1 Zeile)*/
char orig[CONFIG_BUFFERSIZE]; /* Originalpuffer zum lesen der config-file, um die Log und debug-ausgabe zu realisieren */
int i; /* Laufvariable */
int lm = 0; /* Zeilen-Nummer */
/* Optionen mit default-werten füllen */
if(reset){
for (i = 0; keywords[i].keyword[0]; i++)
if (keywords[i].def[0])
keywords[i].handler(keywords[i].def, keywords[i].var);
}
/* config-file öffnen */
if (!(in = fopen(file, "r"))) {
#ifndef NO_LOGING
if(get_flag(LOG_ERROR_FLAG)){
sprintf(get_error_buffer(), "Kann Config-File: %s nicht öffnen!",file);
log_error(get_error_buffer());
}
#endif
DEBUGOUT2("Kann Config-File: %s nicht öffnen!\n", file);
return 0;
}
/* Datei Zeilenweise lesen */
while (fgets(buffer, CONFIG_BUFFERSIZE, in)) {
lm++;
/* Zeilenvorschübe gegen null-terminierungs-Zeichen ersetzen */
if (strchr(buffer, '\n')) *(strchr(buffer, '\n')) = '\0';
/* Originlzeile für eventuelle log-, bzw. debug-meldungen */
strcpy(orig, buffer);
/* Kommentazeichen gegen null-terminierungs-Zeichen ersetzen und damit alles dahinter ignorieren */
if (strchr(buffer, '#')) *(strchr(buffer, '#')) = '\0';
if (!(token = strtok(buffer, " \t"))) continue;
if (!(line = strtok(NULL, ""))) continue;
/* eat leading whitespace */
line = line + strspn(line, " \t=");
/* eat trailing whitespace */
for (i = strlen(line); i > 0 && isspace(line[i - 1]); i--);
line[i] = '\0';
for (i = 0; keywords[i].keyword[0]; i++){
if (!strcasecmp(token, keywords[i].keyword)){
if (!keywords[i].handler(line, keywords[i].var)) {
/* Fehler ins Logfile schreiben */
#ifndef NO_LOGING
if(get_flag(LOG_ERROR_FLAG)){
sprintf(get_error_buffer(), "Fehler beim Parsen des Parameters '%s' im file %s, Zeile %d",orig, file, lm);
log_error(get_error_buffer());
}
#endif
DEBUGOUT4("Kann '%s' nicht Parsen (%s:%d)!\n", orig, file, lm);
/* reset back to the default value */
keywords[i].handler(keywords[i].def, keywords[i].var);
}
}
}
}
fclose(in);
return 1;
}

40
seriell/config.h Normal file
View File

@ -0,0 +1,40 @@
/*
weatherdeamon -- Weather Data Capture Program for the
'ELV-PC-Wettersensor-Empfänger'
config.h -- Part of the weatherdeamon
Copyright (C) 2006 Jan Losinski
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
$Id: process.c v 1.00 11 Aug 2006 losinski $
*/
/* Datenstruktur zum Auswerten des Config-Files */
struct config_keyword {
const char *keyword;
int (* const handler)(const char *line, void *var);
void *var;
const char *def;
} ;
/* Config lesen */
int read_config(const char *, int);

115
seriell/definitions.h Normal file
View File

@ -0,0 +1,115 @@
/*
weatherdeamon -- Weather Data Capture Program for the
'ELV-PC-Wettersensor-Empfänger'
definitions.h -- Part of the weatherdeamon
Copyright (C) 2006 Jan Losinski
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
$Id: process.c v 1.00 11 Aug 2006 losinski $
*/
/* Default-Werte ----------------------------------------------------- */
#define DEFAULT_SERIAL_PORT "/dev/ttyS0" /* Serielle Schnittstelle */
#define DEFAULT_DATA_FILE "./data.log" /* Daten-Logfile */
#define DEFAULT_ERROR_FILE "./error.log" /* Error-Logfile */
#define DEFAULT_PG_HOST "localhost" /* Postgres-host */
#define DEFAULT_PG_USER "localuser" /* Postgres-Username */
#define DEFAULT_PG_PASS "" /* Postgres-Passwort */
#define DEFAULT_PG_DATABASE "localbase" /* Postgres-Datenbank */
#define DEFAULT_CONFIG_FILE "./weather.conf" /* Standart-Configdatei */
/*Alle möglichen Definitionen, die in allen code-schnipseln benötigt werden*/
/* Sensor definitionen ------------------------------------------------- */
#define FERNB 0x07 /* Funkfernbedienung */
#define AUSS1 0x00 /* 'einfacher' Außensensor */
#define AUSS2 0x01 /* 'besserer' Außensensor */
#define REGEN 0x02 /* Regensensor */
#define WINDS 0x03 /* Windsensor */
#define INNEN 0x04 /* Innensensor */
#define HELLI 0x05 /* Helligkeitssensor */
#define PYANO 0x06 /* Pyanometer */
/* Fehlermeldungen ------------------------------------------------------*/
#define ERROR_OPEN "sensor-rs232interface: Fehler beim Oeffnen der RS232-Schnittstelle\n"
#define ERROR_OPTIONS "sensor-rs232interface: Fehler bei der Abfrage der Optionen\n"
#define ERROR_AKTIV "sensor-rs232interface: Fehler beim Aktivieren der Optionen\n"
#define ERROR_TIMEOUT "sensor-rs232interface: keine Daten - timeout-Fehler\n"
#define ERROR_POLLING "sensor-rs232interface: keine Daten - polling-Fehler\n"
#define ERROR_READ "sensor-rs232interface: Fehler beim Lesen\n"
#define ERROR_LOGFILE "Log-Error: Kann Logfile nicht öffnen\n"
#define ERROR_FORK "Fork-Fehler: Kann den Prozess nicht in den Hintergrund schieben\n"
/* Parameter-Flags ----------------------------------------------------- */
#define LOG_ERROR_FLAG 0x01
#define LOG_DATA_FLAG 0x02
#define FOREGROUND_FLAG 0x04
#define VERBOSE_FLAG 0x08
/* Puffergrößen -------------------------------------------------------- */
#define LOG_BUFFERSIZE 100 /* Größe für den Log-Puffer in process.c */
#define ERR_BUFFERSIZE 512 /* Größe für den error-Puffer in main.c */
#define INPUT_BUFFERSIZE 8 /* Größe für den Input-Puffer in input.c */
#define CONFIG_BUFFERSIZE 512 /* Größe des Puffers zum Config-einlesen */
#define QUERY_BUFFERSIZE 512 /* Größe des Zeichenpuffers für SQL-Anfragen */
/* Timeout-Zeiten ------------------------------------------------------ */
#define INPUT_TIMEOUT 10
/* serial protocol definitions ----------------------------------------- */
#define STX 0x02 /* Startbyte */
#define ETX 0x03 /* Endbyte */
/* Verschiedenes ------------------------------------------------------- */
#define FALSE 0
#define TRUE 1
/* Debug --------------------------------------------------------------- */
#ifdef DEBUG
#define DEBUGOUT1(x) fprintf(stderr,x)
#define DEBUGOUT2(x,y) fprintf(stderr,x,y)
#define DEBUGOUT3(x,y,z) fprintf(stderr,x,y,z)
#define DEBUGOUT4(x,y,z,a) fprintf(stderr,x,y,z,a)
#define DEBUGOUT5(x,y,z,a,b) fprintf(stderr,x,y,z,a,b)
#define FOR(x) for(x)
#else
#define DEBUGOUT1(x)
#define DEBUGOUT2(x,y)
#define DEBUGOUT3(x,y,z)
#define DEBUGOUT4(x,y,z,a)
#define DEBUGOUT5(x,y,z,a,b)
#define FOR(x)
#endif
/* Dumping der Daten --------------------------------------------------- */
#ifndef NO_LOGING
#define LOG_DATA(x,y) log_data(x.y)
#define LOG_ERROR(x) log_error(x)
#else
#define LOG_DATA(x,y)
#define LOG_ERROR(x)
#endif

171
seriell/input.c Normal file
View File

@ -0,0 +1,171 @@
/*
weatherdeamon -- Weather Data Capture Program for the
'ELV-PC-Wettersensor-Empfänger'
input.c -- Part of the weatherdeamon
Copyright (C) 2006 Jan Losinski
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
$Id: process.c v 1.00 11 Aug 2006 losinski $
*/
#include <string.h>
#include <time.h>
#include <stdio.h>
#include <fcntl.h> /* File control definitions */
#include <termios.h> /* POSIX terminal control definitions */
#include <sys/types.h>
#include <poll.h> /* Polling */
#include "config.h"
#include "definitions.h"
#include "main.h"
static int fd; /* File-Deskriptor */
static void check_data(int, u_char*);
static int set_port();
static void clean_port(void *);
static int set_port()
{
/** Diese Funktion stellt die Schnittstelle zum RS232 Port zur Verfuegung. *
* Gleichzeitig werden die Optionen so eingestellt, dass ein Abfragen der *
* Daten moeglich ist. *
* Zurueck gegeben wird der Filedeskriptor. */
struct termios options; /* Optionen Schnittstelle */
int fd; /* File-Deskriptor */
/* oeffnen der Schnittstelle - nur lesen, nicht blockierend */
if ((fd = open(global_opts.device,O_RDONLY | O_NONBLOCK | O_NOCTTY | O_NDELAY)) < 0)
exit_error(ERROR_OPEN);
/* Erstmal alles zurücksetzen*/
cfmakeraw(&options);
/* Uebertragungsgeschwindigkeit 19200 Baud */
cfsetispeed(&options, B19200);
/* Control-Flags fertig codiert, funktioniert so!
* (so lange mit minicom rumgespielt bis es geklappt hat)
* wer lust hat kann das gern dekodieren und die Flags einzeln setzen.*/
options.c_cflag = 0x80000BFE;
/* Output-Flags brauchmer net*/
options.c_oflag = 0;
/* Break-conditions ignorieren wir einfach*/
options.c_iflag = IGNBRK;
/* Local-Flags brauchmer auch keine*/
options.c_lflag = 0;
/* Zeug für die Flusskontrolle */
//options.c_cc[VMIN] = 1;
//options.c_cc[VTIME] = 5;
tcflush(fd, TCIFLUSH);
if ( tcsetattr(fd, TCSANOW, &options) != 0 ) /* Optionen schreiben */
exit_error(ERROR_AKTIV);
DEBUGOUT2("\nInterface '%s' offen\n", global_opts.device);
return fd;
}
/* Diese Funktion liest einen Datensatz der seriellen Schnittstelle aus *
* und gibt diesen nach STDOUT. *
* Uebergeben wird der Filedeskriptor. */
int read_port(){
fd = set_port();
int len=0; /* Anzahl gelesener Daten */
int i, readlen =1; /* Laufvariable, Lesezähler */
u_char buffer[INPUT_BUFFERSIZE], *temp = NULL; /* Lesepuffer, Temp-Zeiger */
struct pollfd pfd = {fd, POLLIN, (short)NULL}; /* polling-Optionen */
temp = buffer; /* Temporärer Zeiger bekommt die Anfangsaddresse vom Puffer */
add_clean(clean_port, &fd);
DEBUGOUT1("\nWarte auf Daten\n\n");
do {
if((len = poll(&pfd, 1, INPUT_TIMEOUT)) > 0){ /* warten auf Eingabepuffer */
len = read(fd, temp, 1); /* Zeichenweise lesen */
if(readlen == 1){ /* Solange noch nix verwertbares gelesen wurde auf das Startbyte prüfen */
if(*temp == STX){
temp++; /* Wenn startbyte gefunden Zeiger auf das 2. Puffer-Element setzen */
readlen++; /* Und Lese-Zähler erhöhen */
}
} else { /* Wenn schon was relevantes gelesen wurde */
if(readlen == 8 && *temp == ETX){ /* Wenn schon 8 Byte gelesen wurden und das letzte Byte das Stoppbyte ist */
FOR(i=0; i < readlen; i++)
DEBUGOUT2("%x ",buffer[i]);
DEBUGOUT1("\n");
check_data(readlen,buffer); /* Daten nochmals Prüfen und verarbeiten */
DEBUGOUT1("------------------------------------------\n");
readlen = 1; /* Lesezähler zurücksetzen */
temp = buffer; /* Temp.-Zeiger wieder auf Pufferanfang setzen */
} else { /* Wenn schon was relevantes da war, aber noch keine 8 byte incl. Stoppbyte */
if(*temp == ETX || readlen >= 8){ /* Wenn das aktuelle byte das Stoppbyte oder das 8. Byte, dann sind die daten nicht ok */
readlen = 1; /* Lesezähler zurücksetzen */
temp = buffer; /* Temp-Zeiger auf Pufferanfang */
} else { /* Sonst */
readlen++; /* Lesezähler erhöhen */
temp++; /* Temp.-Zeiger auf das nächste element setzen */
}
}
}
//write(STDOUT_FILENO, buffer, n); /* Ausgabe Messung */
}
} while (buffer[0] != '$'); /* Ende Datensatz */
close(fd); /* Schnittstelle schliessen */
return 1;
}
/* Überprüfung, ob die Struktur der Daten stimmt
* es sollten 8 Byte ankommen:
* <STX><Typ><W1><W2><W3><W4><W5><EXT>
* wobei <STX> = 02h
* und <EXT> = 03h
* Bei <Typ>,<W1>...<W7> ist bit 7 (MSB) immer gesetzt, gehört also nicht zu den Daten!
* Im <Typ>-Byte sind die unteren 4 bit die Addresse und die oberen 3 (weil 7. ist ja nicht benutzt)
* der Typ des Sensors.
* Die Typenzuordnung steht in der definitions.h.
* <W1>...<W7> sind die Werte des Sensors.
* Eine genaue Beschreibung ist unter
* http://www.elv-downloads.de/service/manuals/PC-WS-Testempfaenger/39061-PCSensor_km.pdf
* zu finden. */
static void check_data(int len, u_char *buffer){
time_t timestamp = time(NULL);
if(len==8){
if(buffer[0]==STX && check_msb_set(buffer[1]) && buffer[7]==ETX){
process_data(timestamp, buffer);
}
}
}
static void clean_port(void *data){
close(*((int *)data));
DEBUGOUT1("\nPort geschlossen\n");
}

28
seriell/input.h Normal file
View File

@ -0,0 +1,28 @@
/*
weatherdeamon -- Weather Data Capture Program for the
'ELV-PC-Wettersensor-Empfänger'
input.h -- Part of the weatherdeamon
Copyright (C) 2006 Jan Losinski
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
$Id: process.c v 1.00 11 Aug 2006 losinski $
*/
/*Funktionen*/
int read_port(int);

304
seriell/main.c Normal file
View File

@ -0,0 +1,304 @@
/*
weatherdeamon -- Weather Data Capture Program for the
'ELV-PC-Wettersensor-Empfänger'
main.c -- Part of the weatherdeamon
Copyright (C) 2006 Jan Losinski
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
$Id: process.c v 1.00 11 Aug 2006 losinski $
*/
#include <stdlib.h> /* EXIT_SUCCESS */
#include <errno.h>
#include <unistd.h> /* STDOUT_FILENO */
#include <stdio.h>
#include <fcntl.h> /* O_WRONLY O_APPEND O_CREAT ... */
#include <string.h>
#include "definitions.h"
#include "config.h"
#include "main.h"
/* Variablen ---------------------------------------------------------- */
w_opts global_opts;
clean_struct_ptr clean_ptr = NULL;
#ifndef NO_LOGING
static char *error_buffer = NULL; /* Puffer für Fehler-ausgaben */
#endif
/* Funktionen ----------------------------------------------------------*/
static void background();
static void write_help();
static void merge_options(w_opts *);
#ifndef NO_LOGING
static void log_message(char *, time_t, char *);
static int close_logfile(int);
static int open_logfile(char *);
#endif
static clean_struct_ptr get_last_clean(clean_struct_ptr);
static void clean();
/* Jetzt gehts los.... --------------------------------------------------*/
/* Main-Funktion */
int main(int argc, char *argv[]){
char *extra_conf_file = NULL;
char c;
w_opts opts; /* temp. Optionen */
/* errno 0 setzen */
errno = 0;
/* temp. opts initialisieren (0 setzen) */
opts.flags = 0;
opts.device = NULL;
#ifndef NO_LOGING
opts.data_log = NULL;
opts.error_log = NULL;
#endif
DEBUGOUT1("Programm gestartet\n");
read_config(DEFAULT_CONFIG_FILE,1);
/* Optionen auswerten */
while ((c = getopt (argc, argv, "vfc:e:d:i:h")) != -1)
switch (c) {
#ifndef NO_LOGING
case 'e':
opts.flags |= LOG_ERROR_FLAG;
opts.error_log = optarg;
break;
case 'd':
opts.flags |= LOG_DATA_FLAG;
opts.data_log = optarg;
break;
#endif
case 'c':
extra_conf_file = optarg;
break;
case 'v':
opts.flags |= VERBOSE_FLAG;
break;
case 'f':
opts.flags |= FOREGROUND_FLAG;
break;
case 'i':
opts.device = optarg;
break;
case 'h':
write_help();
return 0;
case '?':
write_help();
return 1;
}
/* eventuelle 2. config-file (mit -c angegeben) auswerten */
if(extra_conf_file != NULL){
read_config(extra_conf_file,0);
}
/* Komandozeilen-Optionen zu denen aus der Config-File hinzufügen */
merge_options(&opts);
/* Debug-Ausgaben, um zu sehen, ob die Optionen richtig gesetzt werden */
DEBUGOUT1("\nOptionen:\n");
DEBUGOUT2(" Device = %s\n", global_opts.device);
DEBUGOUT2(" Foreground: %i\n", get_flag(FOREGROUND_FLAG));
DEBUGOUT2(" Verbose: %i\n", get_flag(VERBOSE_FLAG));
DEBUGOUT2(" LogData: %i\n", get_flag(LOG_DATA_FLAG));
DEBUGOUT2(" DataFile = %s\n", global_opts.data_log);
DEBUGOUT2(" LogError: %i\n", get_flag(LOG_ERROR_FLAG));
DEBUGOUT2(" ErrorFile = %s\n", global_opts.error_log);
DEBUGOUT1("\nPostgres:\n");
DEBUGOUT2(" Host: = %s\n",global_opts.pg_host);
DEBUGOUT2(" User: = %s\n",global_opts.pg_user);
DEBUGOUT2(" Pass: = %s\n",global_opts.pg_pass);
DEBUGOUT2(" Datenbank = %s\n",global_opts.pg_database);
/* Programm in den Hintergrund schicken ? */
background();
DEBUGOUT1("\nBeginne Interface zu öffnen\n\n");
/* Port Pollen */
read_port();
/* Theoretisch sollte das Programm hier _nie_ hinkommen */
clean();
return EXIT_SUCCESS;
}
/* Diese Funktion ist dazu da, das Programm in den Hintergrund zu Forken */
static void background(){
if (!get_flag(FOREGROUND_FLAG)){
DEBUGOUT1("Forke in den Hintergrund");
if (daemon(0, get_flag(VERBOSE_FLAG)) == -1) {
exit_error(ERROR_FORK);
}
}
}
/* Führt die Optionen aus der Komandozeile und die aus dem Conf-File zusammen */
static void merge_options(w_opts *priv){
if((*priv).device != NULL)
global_opts.device = (*priv).device;
if((*priv).data_log != NULL)
global_opts.data_log = (*priv).data_log;
if((*priv).error_log != NULL)
global_opts.error_log = (*priv).error_log;
global_opts.flags |= (*priv).flags;
}
/* Bisschen Hilfe ausgeben */
static void write_help(){
printf("Usage:\n");
#ifndef NO_LOGING
printf("weatherdeamon [-f] [-v] [-i <interface>] [-c <Conf-File>] [-d <Data-logfile>] [-e <Error-Logfile>]\n");
#else
printf("weatherdeamon [-i <interface>]\n");
#endif
printf("\t-i <interface>\n\t\tThe interface where the reciver is connected \n\t\t(default:/dev/ttyS0)\n");
printf("\t-f\n\t\tDon't Fork to background\n");
printf("\t-v\n\t\tVerbose, log errors to stdout, even it's forked to background\n");
printf("\t-c <Conf-File>\n\t\t tells the Program to use an aditional config-file\n");
#ifndef NO_LOGING
printf("\t-d <Data-logfile>\n\t\tLog all Data to the given Logfile\n\t\t(default: no logging!)\n");
printf("\t-e <Error-Logfile>\n\t\tLog all non-critical-Errors to the given Logfile\n\t\t(default: no logging!)\n");
#endif
}
/* ein Flag lesen */
int get_flag(int mask){
return (global_opts.flags & mask) != 0 ;
}
/* Diese Funktion beendet das Programm mit einer Fehlermeldung. */
void exit_error(char* err)
{
clean();
if(errno != 0){
perror("Fehler");
}
write(STDOUT_FILENO, err, strlen(err));
exit(1);
}
/* Funktionen für die Logfiles */
#ifndef NO_LOGING
/* Schreiben einer Fehlermeldung in das fehler-Logfile */
void log_error(char *msg){
if(get_flag(LOG_ERROR_FLAG)){
log_message(global_opts.error_log, time(NULL), msg);
DEBUGOUT1(" -->Error Logged \n");
}
}
/* Schreiben eines Datensatzes in das Daten-Logfile */
void log_data(time_t timestamp, char *msg){
log_message(global_opts.data_log, time(NULL), msg);
DEBUGOUT1(" -->Data Logged \n");
}
/* Logfile öffnen */
static int open_logfile(char *file){
int log_fd;
log_fd = open(file, O_WRONLY | O_APPEND | O_CREAT, 00600);
if (log_fd < 0) {
exit_error(ERROR_LOGFILE);
}
return log_fd;
}
/* Logfile schließen */
static int close_logfile(int log_fd){
fsync(log_fd);
close(log_fd);
}
/* Nachicht schreiben */
static void log_message(char *file, time_t timestamp, char *msg){
int log_fd;
char date[27];
log_fd=open_logfile(file);
snprintf(date, 27, (char *)asctime(localtime(&timestamp)));
write(log_fd, date + 4, strlen(date) - 5);
write(log_fd, " - ", 3);
write(log_fd, msg, strlen(msg));
write(log_fd, "\n", 1);
close_logfile(log_fd);
}
char *get_error_buffer(){
if(error_buffer == NULL){
error_buffer = malloc(sizeof(char)*ERR_BUFFERSIZE);
}
return error_buffer;
}
#endif
/* Pointer auf letztes 'Clean-Element' bekommen.
* Mir war grad nach rekrusiv und so viele Elemente sollten
* es ja nicht sein.*/
static clean_struct_ptr get_last_clean(clean_struct_ptr ptr){
if(ptr != NULL){
if (ptr->next != NULL){
return get_last_clean(ptr->next);
} else {
return ptr;
}
}
return NULL;
}
/* Ein neues Clean-Element anfügen. Ein Clean-Element ist eine Datenstruktur, die
* einen Pointer auf eine Funktion vom Typ
* void func(void *data),
* einen Zeiger auf beliebige Daten und einen Zeiger auf das nächste Element hält.
* Die Funktionen werden beim regulären beenden des Programmes aufgerufen um zum bsp.
* datenbankverbindungen zu schließen, etc. */
void add_clean(void (*func)(void *data), void *data){
clean_struct_ptr p, temp = (clean_struct_ptr) malloc(sizeof(clean_data));
temp->data = data;
temp->func = func;
temp->next = NULL;
if(clean_ptr == NULL){
clean_ptr = temp;
} else {
p = get_last_clean(clean_ptr);
p->next = temp;
}
}
/* 'Säuberung' ausführen */
static void clean(){
clean_struct_ptr p = clean_ptr;
while(p != NULL){
p->func(p->data);
p = p->next;
}
}

90
seriell/main.h Normal file
View File

@ -0,0 +1,90 @@
/*
weatherdeamon -- Weather Data Capture Program for the
'ELV-PC-Wettersensor-Empfänger'
main.h -- Part of the weatherdeamon
Copyright (C) 2006 Jan Losinski
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
$Id: process.c v 1.00 11 Aug 2006 losinski $
*/
/* Datenstrukturen --------------------------------------------------------*/
/* Optionen */
typedef struct {
unsigned char flags; /* Flags */
char *device; /* Das Serielle Device */
char *pg_host; /* Postgres-Host */
char *pg_user; /* Postgres-Username */
char *pg_pass; /* Postgres-Password */
char *pg_database; /* Postgres-Datenbank */
#ifndef NO_LOGING
char *data_log; /* Das Daten-Logfile */
char *error_log; /* Das Fehler-Logfile */
#endif
} w_opts;
/* Aufräumfunktionen */
/* TODO: sollen Funktionen werden, mit denen die eintelnen Teile funktionen registrieren können, die aufräiumen
* (Verbindung schließen, file schließen, ...) */
typedef struct clean_struct *clean_struct_ptr;
typedef struct clean_struct {
void *data;
void (*func)(void *data);
clean_struct_ptr next;
} clean_data;
/* Funktionen -------------------------------------------------------------*/
/* Programm mit einem Fatalem Fehler beenden.
* Argument: Fehlermeldung */
void exit_error(char*);
/* Ein Flag bekommen
* Argument: Maske für das Flag, siehe definitions.h */
int get_flag(int);
#ifndef NO_LOGING
/* Schreiben einer Fehlermeldung in ein Fehler-Log
* Das Argument ist die Fehermeldung */
void log_error(char *);
/* Schreiben eines Datensatzes in das Logfile
* 1. Argument: Timestamp
* 2. Argument: Log-Message */
void log_data(time_t, char *);
/* Gibt _EINEN_ Puffer für das Zusammensetzen
* der Fehler-Zeichenketten zurück.
* Es sollte wirklich bei jedem Aufruf der selbe
* Puffer sein */
char *get_error_buffer();
#endif
/* Ein neues Clean-Element anfügen. Ein Clean-Element ist eine Datenstruktur, die
* einen Pointer auf eine Funktion vom Typ
* void func(void *data),
* einen Zeiger auf beliebige Daten und einen Zeiger auf das nächste Element hält.
* Die Funktionen werden beim regulären beenden des Programmes aufgerufen um zum bsp.
* datenbankverbindungen zu schließen, etc. */
void add_clean(void (*func)(void *data), void *data);
/* Variablen --------------------------------------------------------------*/
extern w_opts global_opts;

347
seriell/process.c Normal file
View File

@ -0,0 +1,347 @@
/*
weatherdeamon -- Weather Data Capture Program for the
'ELV-PC-Wettersensor-Empfänger'
process.c -- Part of the weatherdeamon
Copyright (C) 2006 Jan Losinski
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
$Id: process.c v 1.00 11 Aug 2006 losinski $
*/
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include <sys/types.h>
#include <string.h>
#include "main.h"
#include "definitions.h"
#include "config.h"
#include "write.h"
/* Funktionsdefinitionen */
static u_char get_bit(u_char, u_char);
static u_char get_2bits(u_char, u_char);
static u_char get_hi_nibble(u_char);
static u_char get_lo_nibble(u_char);
static u_char remove_msb(u_char);
static int convert_signed_int(u_char, u_char);
static unsigned int convert_unsigned_int(u_char, u_char);
static auss1_data process_auss1(time_t, u_char, u_char *);
static auss2_data process_auss2(time_t, u_char, u_char *);
static regen_data process_regen(time_t, u_char, u_char *);
static winds_data process_winds(time_t, u_char, u_char *);
static innen_data process_innen(time_t, u_char, u_char *);
static helli_data process_helli(time_t, u_char, u_char *);
static pyano_data process_pyano(time_t, u_char, u_char *);
static void check_log_buffer();
static char* prepend_type_address(u_char, u_char);
/* globale Variablen */
char *log_buffer = NULL; /* Puffer für die Log-Ausgabe */
unsigned int last_rain_count = -1; /* Letzter gemessener Wasserstand */
/* Bestimmung der Sensoren und Weiterreichung an die Funktionen zum auswerten der Werte
* sowie zum wegschreiben */
void process_data(time_t timestamp, u_char *buffer){
u_char type; /* Sensortyp */
u_char address; /* Sensoraddresse */
type = get_hi_nibble(remove_msb(buffer[1]));
address = get_lo_nibble(buffer[1]);
DEBUGOUT1(asctime(localtime(&timestamp)));
switch (type){
case FERNB :
DEBUGOUT2("Fernbedienung an Addresse %i\n", address);
DEBUGOUT1("\nnoch nix zu implementiert!\n\n");
break;
case AUSS1 :
write_auss1(process_auss1(timestamp,address, buffer));
break;
case AUSS2 :
write_auss2(process_auss2(timestamp,address, buffer));
break;
case REGEN :
write_regen(process_regen(timestamp,address, buffer));
break;
case WINDS :
write_winds(process_winds(timestamp,address, buffer));
break;
case INNEN :
write_innen(process_innen(timestamp,address, buffer));
break;
case HELLI :
write_helli(process_helli(timestamp,address, buffer));
break;
case PYANO :
write_pyano(process_pyano(timestamp,address, buffer));
break;
}
}
/* Wertkonvertierungen --------------------------------------------------- */
/* Wertkonvertierungen für den 'einfachen' Außensensor */
static auss1_data process_auss1(time_t timestamp, u_char address, u_char *buffer){
auss1_data data; /* Datenstruktur */
data.timestamp = timestamp; /* Zeitstempel */
data.address = address; /* Addresse */
data.temp = convert_signed_int(buffer[2],buffer[3]); /* Temparatur */
DEBUGOUT2("Aussensensor1 an Addresse %i\n", address);
DEBUGOUT2("Temp.: %3.1f\n", (data.temp*0.1));
#ifndef NO_LOGING
if(get_flag(LOG_DATA_FLAG)){
check_log_buffer();
sprintf(prepend_type_address(AUSS1,address), "Temp: %3.1f°C",(data.temp*0.1));
log_data(timestamp, log_buffer);
}
#endif
return data;
}
/* Wertkonvertierungen für den 'besseren' Außensensor */
static auss2_data process_auss2(time_t timestamp, u_char address, u_char *buffer){
auss2_data data; /* Datenstruktur */
data.timestamp = timestamp; /* Zeitstempel */
data.address = address; /* Addresse */
data.temp = convert_signed_int(buffer[2],buffer[3]); /* Temparatur */
data.hum = remove_msb(buffer[4]); /* Luftfeuchte */
DEBUGOUT2("Aussensensor2 an Addresse %i\n", address);
DEBUGOUT3("Temp.: %3.1f°C Feuchte: %d%%\n",(data.temp*0.1),data.hum);
#ifndef NO_LOGING
if(get_flag(LOG_DATA_FLAG)){
check_log_buffer();
sprintf(prepend_type_address(AUSS2,address), "Temp: %3.1f°C Hum: %d%%",(data.temp*0.1),data.hum);
log_data(timestamp, log_buffer);
}
#endif
return data;
}
/* Wertkonvertierungen für den Regensensor (ein Zählschritt = 370ml/m^2)*/
static regen_data process_regen(time_t timestamp, u_char address, u_char *buffer){
regen_data data; /* Datenstruktur */
unsigned int new_rain_count = 0; /* Neuer Zählerstand */
unsigned int now_rain_count = 0; /* Delta-Zählerstand */
data.timestamp = timestamp; /* Zeitstempel */
data.address = address; /* Addresse */
new_rain_count = ((buffer[2] & 0x1F) << 7) | remove_msb(buffer[3]); /* Niederschlagszähler */
if(last_rain_count == -1) /* Nach Programmstart Zähler initialisieren */
last_rain_count = new_rain_count;
now_rain_count = new_rain_count - last_rain_count; /* neuen Niederschlag berechnen */
if(now_rain_count < 0){ /* Wenn Integerüberlauf im Sensor */
now_rain_count = (0x3FFF - last_rain_count) + new_rain_count; /* Dann letzten gemessenen Wert vom Max-Integer-Wert abziehen und neuen Zählwert dazurechnen */
DEBUGOUT1("Integer-Überlauf\n");
}
data.counter = (now_rain_count * 370); /* Ein Zählschritt entspricht 370ml/m^2, also änderung mit 370 multiplizieren und zuweisen */
last_rain_count = new_rain_count; /* Zähler neu setzen */
DEBUGOUT2("Regensensor an Addresse %i\n", address);
DEBUGOUT3("Zähler: %d Differenz: %d\n", new_rain_count,now_rain_count);
DEBUGOUT2("Niederschlag: %dml/m^2\n", data.counter);
#ifndef NO_LOGING
if(get_flag(LOG_DATA_FLAG)){
check_log_buffer();
sprintf(prepend_type_address(REGEN,address), "Rain: %dml/m^2",data.counter);
log_data(timestamp, log_buffer);
}
#endif
return data;
}
/* Wertkonvertierungen für den Windsensor */
static winds_data process_winds(time_t timestamp, u_char address, u_char *buffer){
winds_data data; /* Datenstruktur */
data.timestamp = timestamp; /* Zeitstempel */
data.address = address; /* Addresse */
data.geschw = convert_unsigned_int(buffer[2],buffer[3]); /* Windgeschwindigkeit */
data.schwank = buffer[4] & 0x03; /* Schwankungsbreite */
data.richt = convert_unsigned_int(buffer[5],buffer[6]); /* Windrichtung */
DEBUGOUT2("Windsensor an Addresse %i\n", address);
DEBUGOUT4("Geschw.: %3.1fKm/h Schwank: %d Richtung: %d°\n",(data.geschw*0.1),data.schwank,data.richt);
#ifndef NO_LOGING
if(get_flag(LOG_DATA_FLAG)){
check_log_buffer();
sprintf(prepend_type_address(WINDS,address), "Spd: %3.1fKm/h Fluct: %d%% Dir:%d°",(data.geschw*0.1),data.schwank,data.richt);
log_data(timestamp, log_buffer);
}
#endif
return data;
}
/* Wertkonvertierungen für den Innensensor */
static innen_data process_innen(time_t timestamp, u_char address, u_char *buffer){
innen_data data; /* Datenstruktur */
data.timestamp = timestamp; /* Zeitstempel */
data.address = address; /* Addresse */
data.temp = convert_signed_int(buffer[2],buffer[3]); /* Temparatur */
data.hum = remove_msb(buffer[4]); /* Luftfeuchte */
data.press = convert_unsigned_int(buffer[5],buffer[6]); /* Luftdruck */
DEBUGOUT2("Innensensor an Addresse %i\n",address);
DEBUGOUT4("Temp.: %3.1f°C Feuchte: %d%% Druck: %dhPa\n",(data.temp*0.1),data.hum,data.press);
#ifndef NO_LOGING
if(get_flag(LOG_DATA_FLAG)){
check_log_buffer();
sprintf(prepend_type_address(INNEN,address), "Temp: %3.1f°C Hum: %d%% Press: %dhPa",(data.temp*0.1),data.hum,data.press);
log_data(timestamp, log_buffer);
}
#endif
return data;
}
/* Wertkonvertierungen für den Helligkeitssensor */
static helli_data process_helli(time_t timestamp, u_char address, u_char *buffer){
helli_data data; /* Datenstruktur */
data.timestamp = timestamp; /* Zeitstempel */
data.address = address; /* Addresse */
data.rawlum = convert_unsigned_int(buffer[2],buffer[3]); /* 'Roh-Helligkeit' - Helligkeit ohne Multiplikator */
data.mult = buffer[4] & 0x03; /* Multiplikator */
data.abslum = (0x01 << data.mult) * data.rawlum; /* Absolute Helligkeit */
DEBUGOUT2("Helligkeitssensor an Addresse %i\n", address);
DEBUGOUT4("Rel. Hell.: %d Mult.: %d Abs. Hell.: %d\n",data.rawlum,data.mult,data.abslum);
#ifndef NO_LOGING
if(get_flag(LOG_DATA_FLAG)){
check_log_buffer();
sprintf(prepend_type_address(HELLI,address), "Bright: %d",data.abslum);
log_data(timestamp, log_buffer);
}
#endif
return data;
}
/* Wertkonvertierungen für das Pyanometer */
static pyano_data process_pyano(time_t timestamp, u_char address, u_char *buffer){
pyano_data data; /* Datenstruktur */
data.timestamp = timestamp; /* Zeitstempel */
data.rawrad = convert_unsigned_int(buffer[2],buffer[3]); /* 'Roh-Strahlung' - Strahlung ohne Multiplikator */
data.mult = buffer[4] & 0x03; /* Multiplikator */
data.absrad = (0x01 << data.mult) * data.rawrad; /* Absolute Strahlung */
DEBUGOUT2("Pyanometer an Addresse %i\n", address);
DEBUGOUT4("Rel. Strahl.: %d Mult.: %d Abs. Strahl.: %d\n",data.rawrad,data.mult,data.absrad);
#ifndef NO_LOGING
if(get_flag(LOG_DATA_FLAG)){
check_log_buffer();
sprintf(prepend_type_address(PYANO,address), "Int: %d",data.absrad);
log_data(timestamp, log_buffer);
}
#endif
return data;
}
/* Verschiedenes ----------------------------------------------------------*/
/* einen vorzeichenbehafteten 14-Bit Binärwert in einen Int umwandeln*/
static int convert_signed_int(u_char hi_byte, u_char lo_byte){
int val;
val = convert_unsigned_int(hi_byte,lo_byte);
if (get_bit(val,14)){
val |= ~0x3FFF;
}
return val;
}
/* einen 14-Bit Binärwert in einen Int umwandeln*/
static unsigned int convert_unsigned_int(u_char hi_byte, u_char lo_byte){
return (remove_msb(hi_byte) << 7) | remove_msb(lo_byte);
}
/* Ein Bit vom Byte */
static u_char get_bit(u_char byte, u_char bit){
return byte >> bit & 0x01;
}
/* 2 Bit vom Byte */
static u_char get_2bits(u_char byte, u_char bit){
return byte >> bit & 0x03;
}
/* oberes halbbyte */
static u_char get_hi_nibble(u_char byte){
return byte >> 4 & 0x0f;
}
/* unteres halbbyte */
static u_char get_lo_nibble(u_char byte){
return byte & 0x0f;
}
/* Erstes Bit 0 setzen */
static u_char remove_msb(u_char byte){
return (byte & 0x7f);
}
/* Checkt, das das MSB gesetzt ist */
int check_msb_set(u_char byte){
return (byte & 0x80);
}
#ifndef NO_LOGING
/* Prüfen ob Puffer für Logausgaben angelegt und renn nicht, dann anlegen */
static void check_log_buffer(){
if (log_buffer == NULL){
log_buffer = malloc(sizeof(char)*LOG_BUFFERSIZE);
}
}
/* In der Log-Zeile die Addresse und den Typ des Sensors davorbauen
* gibt die Addresse zurück, an der die Werte weitergeschrieben werden können */
static char* prepend_type_address(u_char type, u_char address){
return (log_buffer + sprintf(log_buffer, "Sens: %i:%i - ", type, address));
}
#endif

29
seriell/process.h Normal file
View File

@ -0,0 +1,29 @@
/*
weatherdeamon -- Weather Data Capture Program for the
'ELV-PC-Wettersensor-Empfänger'
process.h -- Part of the weatherdeamon
Copyright (C) 2006 Jan Losinski
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
$Id: process.c v 1.00 11 Aug 2006 losinski $
*/
/*Funktionen*/
int check_msb_set(u_char);
void process_data(time_t, u_char*);

26
seriell/weather.conf Normal file
View File

@ -0,0 +1,26 @@
# Die Serielle Schnittstelle
interface /dev/ttyS0 # default: /dev/ttyS0
# Sollen Daten in ein Logfile geschrieben werden?
log_data yes # default: no
# Sollen Fehler in ein Logfile geschrieben werden?
log_error yes # default: no
# Das File wo die daten reinkommen
data_file ../data.log # default: ./data.log
# Das File wo die Fehler reinkommen
error_file ../error.log # default: ./error.log
# Im Vordergrunf bleiben?
foreground yes # default: no
# Fehlermeldungen nach stderr schicken?
verbose yes # default: no
# Postgres-Einstellungen
pg_host 141.30.228.39
pg_user losinshi
#pg_pass
pg_database wetter

157
seriell/write.c Normal file
View File

@ -0,0 +1,157 @@
/*
weatherdeamon -- Weather Data Capture Program for the
'ELV-PC-Wettersensor-Empfänger'
write.c -- Part of the weatherdeamon
Copyright (C) 2006 Jan Losinski
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
$Id: process.c v 1.00 11 Aug 2006 losinski $
*/
/*
* Allgemeines zu dieser File:
*
* Sollte irgend jemand das Programm weiter verwenden,
* jedoch die Daten anders oder woandershin wegschreiben
* wollen, so müssen nur diese Funktionen neu implementiert
* werden.
*/
#include <stdio.h>
#include <stdlib.h>
#include <postgresql/libpq-fe.h>
#include "definitions.h"
#include "main.h"
#include "write.h"
/* Globale Variablen -----------------------------------------*/
static char *query_buffer = NULL;
static PGconn *connection = NULL;
static char *conn_string = NULL;
/* Funktionen ----------------------------------------------- */
static void check_create_query_buffer();
static int pg_connect();
static void pg_insert(char *);
static void clean_write(void *);
/* Funktionen zum wegschreiben -------------------------------*/
/* 'einfacher' Außensensor */
void write_auss1(auss1_data data){
check_create_query_buffer();
snprintf(query_buffer, QUERY_BUFFERSIZE, "INSERT INTO auss1_data (sens_id, \"temp\") VALUES (get_sensor_id(%d,%d),%d)",AUSS1, data.address, data.temp);
pg_insert(query_buffer);
}
/* 'besserer' Außensensor */
void write_auss2(auss2_data data){
check_create_query_buffer();
snprintf(query_buffer, QUERY_BUFFERSIZE, "INSERT INTO auss2_data (sens_id, \"temp\", hum) VALUES (get_sensor_id(%d,%d),%d,%d)",AUSS2, data.address, data.temp, data.hum);
pg_insert(query_buffer);
}
/* Regensensor */
void write_regen(regen_data data){
check_create_query_buffer();
snprintf(query_buffer, QUERY_BUFFERSIZE, "INSERT INTO regen_data (sens_id, count) VALUES (get_sensor_id(%d,%d),%d)",REGEN, data.address, data.counter);
pg_insert(query_buffer);
}
/* Windsensor */
void write_winds(winds_data data){
check_create_query_buffer();
snprintf(query_buffer, QUERY_BUFFERSIZE, "INSERT INTO winds_data (sens_id, geschw, schwank, richt) VALUES (get_sensor_id(%d,%d),%d,%d,%d)",WINDS, data.address, data.geschw, data.schwank, data.richt);
pg_insert(query_buffer);
}
/* Innensensor */
void write_innen(innen_data data){
check_create_query_buffer();
snprintf(query_buffer, QUERY_BUFFERSIZE, "INSERT INTO innen_data (sens_id, \"temp\", hum, press) VALUES (get_sensor_id(%d,%d),%d,%d,%d)",INNEN, data.address, data.temp, data.hum, data.press);
pg_insert(query_buffer);
}
/* Helligkeitssensor */
void write_helli(helli_data data){
check_create_query_buffer();
snprintf(query_buffer, QUERY_BUFFERSIZE, "INSERT INTO helli_data (sens_id, bight) VALUES (get_sensor_id(%d,%d),%d)",HELLI, data.address, data.abslum);
pg_insert(query_buffer);
}
/* Pyanometer */
void write_pyano(pyano_data data){
check_create_query_buffer();
snprintf(query_buffer, QUERY_BUFFERSIZE, "INSERT INTO pyano_data (sens_id, intens) VALUES (get_sensor_id(%d,%d),%d)",PYANO, data.address, data.absrad);
pg_insert(query_buffer);
}
/* Testen ob Puffer angelegt und bei bedarf anlegen */
static void check_create_query_buffer(){
if(query_buffer == NULL){
query_buffer= malloc(sizeof(char)*QUERY_BUFFERSIZE);
}
}
/* Guckt ob Verbindung da und versucht aufzubauen.
* gibt 1 zurück, wenn erfolgreich, sonst 0 */
static int pg_connect(){
if(PQstatus(connection) != CONNECTION_OK){
if (connection == NULL){
if(conn_string == NULL){
conn_string = malloc(sizeof(char)*255);
snprintf(conn_string, 255, "host=%s dbname=%s user=%s password=%s", global_opts.pg_host, global_opts.pg_database, global_opts.pg_user, global_opts.pg_pass);
}
connection = PQconnectdb(conn_string);
add_clean(clean_write, connection);
} else {
PQreset(connection);
}
if(PQstatus(connection) != CONNECTION_OK){
DEBUGOUT2("\nFehler beim Aufbau der Datenbankverbindung\n%s\n", PQerrorMessage(connection));
snprintf(get_error_buffer(), ERR_BUFFERSIZE, "Fehler beim Aufbau der Datenbankverbindung: %s", PQerrorMessage(connection));
log_error(get_error_buffer());
return 0;
}
DEBUGOUT1("\nDatenbankverbindung erfolgreich hergestellt\n");
}
return 1;
}
static void pg_insert(char *query){
PGresult *res;
if(pg_connect()){
res = PQexec(connection, query);
if(!res || PQresultStatus(res) != PGRES_COMMAND_OK){
DEBUGOUT2("Fehler beim INSERT: %s\n", query);
snprintf(get_error_buffer(), ERR_BUFFERSIZE, "Fehler beim INSERT: %s", query);
log_error(get_error_buffer());
} else {
DEBUGOUT2("Query: '%s' ausgeführt\n", query);
}
PQclear(res);
}
}
static void clean_write(void *data){
PGconn *conn = data;
PQfinish(conn);
DEBUGOUT1("\nVerbindung Geschlossen \n");
}

110
seriell/write.h Normal file
View File

@ -0,0 +1,110 @@
/*
weatherdeamon -- Weather Data Capture Program for the
'ELV-PC-Wettersensor-Empfänger'
write.h -- Part of the weatherdeamon
Copyright (C) 2006 Jan Losinski
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
$Id: process.c v 1.00 11 Aug 2006 losinski $
*/
#include <time.h>
/* Datenstrukturen für die einzelnen Sensoren ------------------------------- */
/* Datenstruktur für den 'einfachen' Außensensor */
typedef struct {
time_t timestamp; /*Zeitstempel*/
unsigned char address; /*Addresse*/
int temp; /*Temparatur*/
} auss1_data ;
/* Datenstruktur für den 'besseren' Außensensor */
typedef struct {
time_t timestamp; /*Zeitstempel*/
unsigned char address; /*Addresse*/
int temp; /*Temparatur*/
unsigned int hum; /*Luftfeuchte*/
} auss2_data;
/* Datenstruktur für den Regensensor */
typedef struct {
time_t timestamp; /*Zeitstempel*/
unsigned char address; /*Addresse*/
unsigned int counter; /*Zählerstand*/
} regen_data;
/* Datenstruktur für den Windsensor */
typedef struct {
time_t timestamp; /*Zeitstempel*/
unsigned char address; /*Addresse*/
unsigned int geschw; /*Windgeschwindigkeit*/
unsigned int schwank; /*Schwankungsbreite*/
unsigned int richt; /*Windrichtung*/
} winds_data;
/* Datenstruktur für den Innensensor */
typedef struct {
time_t timestamp; /*Zeitstempel*/
unsigned char address; /*Addresse*/
int temp; /*Temparatur*/
unsigned int hum; /*Luftfeuchte*/
unsigned int press; /*Luftdruck*/
} innen_data;
/* Datenstruktur für den Helligkeitssensor */
typedef struct {
time_t timestamp; /*Zeitstempel*/
unsigned char address; /*Addresse*/
unsigned int rawlum; /*'Roh-Helligkeit' - Helligkeit ohne Multiplikator*/
unsigned int mult; /*Multiplikator*/
unsigned int abslum; /*Absolute Helligkeit*/
} helli_data;
/* Datenstruktur für das Pyanometer */
typedef struct {
time_t timestamp; /*Zeitstempel*/
unsigned char address; /*Addresse*/
unsigned int rawrad; /*'Roh-Strahlung' - Strahlung ohne Multiplikator*/
unsigned int mult; /*Multiplikator*/
unsigned int absrad; /*Absolute Strahlung*/
} pyano_data;
/* Funktionen zum wegschreiben der Daten ----------------------------------- */
/* 'einfacher' Außensensor */
void write_auss1(auss1_data);
/* 'besserer' Außensensor */
void write_auss2(auss2_data);
/* Regensensor */
void write_regen(regen_data);
/* Windsensor */
void write_winds(winds_data);
/* Innensensor */
void write_innen(innen_data);
/* Helligkeitssensor */
void write_helli(helli_data);
/* Pyanometer */
void write_pyano(pyano_data);