/* L_TENKI (jap. <Wetter>) liest Datenbytes vom Conrad-Telemetrie-Empfänger
* an /dev/ttyS0 und gibt die Daten auf Standard-Ausgabe aus.
*
* Das Programm ist ein Standard-Linux-Programm, geschrieben in C++.
* Es basiert auf dem Windows-Programm tenki von h#s.
*
* Benoetigt werden vier Umrechnungstabellen festen Namens.
* (diese sollten durchaus als Konstanten ins Programm eingebaut werden)
*
* tisc, 01/02
Ein Datenrahmen umfaßt 14 Bytes und ist wie folgt aufgebaut:
Byte Daten
---- -----
1 8 Bit A/D-Wert vom Eingang A (A1)
2 8 Bit A/D-Wert vom Eingang B (A2) Regen
3 8 Bit A/D-Wert vom Eingang C (A3) Windrichtung [360°/256]
4 8 Bit A/D-Wert vom Eingang D (A4) Luftdruck [hPa(Tabelle)]
5 8 Bit A/D-Wert vom Eingang E (A5) Radioaktivität [100µSv/h]
6 8 Bit A/D-Wert vom Eingang F (A6) Licht [Lux(Tabelle)]
7 8 Bit A/D-Wert vom Eingang G (A7) Feuchte [%(Tabelle)]
8 8 Bit A/D-Wert vom Eingang H (A8) Temperatur [°C(Tabelle)]
9 8 Bits vom Digitalport
10 High-Byte des Zähler-/Frequenzmesserwertes Windgeschw.
11 Low-Byte des Zähler-/Frequenzmesserwertes [0.0179 m/s]
12 Minuten-/Stundenwert der Stoppuhr
13 Sekunden-/Minutenwert der Stoppuhr
14 Hundertstel-/Sekundenwert der Stoppuhr
Die Zuordnung der A/D-Wandlerwerte (0...255) zu den physikalischen Meßgrößen
der von uns angebotenen Sensoren erfolgt in den meisten Fällen durch
Tabellendateien.
Die Tabellen berücksichtigen eventuelle Nichtlinearitäten der Sensorkennlinien
und nehmen Rundungen vor.
Byte 12 enthält im MSB das Stopflag (kennzeichnet den letzen Datenrahmen
und die Stoppzeit nach dem Low-High-Übergang am Triggereingang).
Byte 13 enthält im MSB das Zeitformatflag der Stoppuhr:
0 = Minuten:Sekunden:Hundertstel
1 = Stunden:Minuten:Sekunden
Läuft die Stoppuhr länger als eine Stunde, erfolgt automatisch das
Umschalten des Zeitformates. Läuft die Stoppuhr länger als 24 Stunden,
rollt der Stundenwert nach 23 auf 0. Dies kann zum Zählen von Tagen
genutzt werden.
*/
const char* default_device = "/dev/ttyS0"; /* = COM1 */
const long int timeout_sec = 10;
/* wir haben 10 Sekunden, um ein Paket zu empfangen */
const long int timeout_usec = 0;
/* Terminal-IO */
#include <termios.h>
#include <unistd.h>
#include <sys/ioctl.h>
/* open () */
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
/* select() */
#include <sys/time.h>
/* fuer Fehlermeldungen */
#include <errno.h> // fuer Fehlermeldungen zu Fehlercodes
#include <string.h> // fuer strerror() - macht Fehlermeldungen aus Fehlercodes
#include <errno.h>
#include <iostream>
#include <iomanip>
#include <fstream>
#include <string>
// Deklaration der Umrechnungstabellen - die sind am Dateiende der
// Uebersichtlichkeit halber
extern const float kty[256], hyg[256], lux[256], baro[256];
static void my_perror (const string& s)
{
// erstmal die Fehlermeldung abholen
const char *err_msg = strerror (errno);
// C++ konform ausgeben
cerr << s << ": " << err_msg << endl;
}
/*
static bool LiesTabelle(const string& dateiname, float *puffer)
{
//eine Tabelle (Datei) mit 256 float-Werten einlesen, muß neben der .EXE liegen
ifstream datei (dateiname.c_str());
if (datei)
{
for (int i = 0; i < 256; i++, puffer++)
{
datei >> *puffer;
}
return true;
}
return false;
}
*/
void Auswertung(unsigned char* incoming)
{
int windgeschw;
static int letzte_windgeschw = 0;
int h,m,s; // vom Zeit-Diagramm
const static char *richtung[16]=
{ //Norden=0°, Uhrzeiger-Richtung
"Nord","Nord-Nordost","Nordost","Ost-Nordost",
"Ost","Ost-Südost","Südost","Süd-Südost",
"Süd","Süd-Südwest","Südwest","West-Südwest",
"West","West-Nordwest","Nordwest","Nord-Nordwest"
};
// Windgeschwindigkeit vorberechnen:
// Leider hinterläßt der Sender bei stehendem Flügelrad
// den letzten gemessenen Wert konstant, deshalb hier Extrawurst braten
windgeschw = (((int)incoming[9]) << 8) + incoming[10];
if ((windgeschw == letzte_windgeschw) && (windgeschw < 0x30))
{
windgeschw=0;
}
letzte_windgeschw=windgeschw;
//Uhr des Senders auswerten:
if (incoming[12] & 0x80)
{ //Stunden-Minuten-Sekunden
h=incoming[11];
m=incoming[12]&0x7F;
s=incoming[13];
}
else
{ //Minuten-Sekunden-Hundertstel
h=0;
m=incoming[11];
s=incoming[12];
}
// Ergebnisse ausgeben
//
char timestr[256];
time_t cur_time = time (0L);
struct tm* local_time = localtime(&cur_time);
strftime (timestr, 256, "%c", local_time);
cout << "Uhrzeit (lokal): " << timestr << endl;
ios::fmtflags old_flags = cout.flags();
cout.setf (ios::fixed);
cout << "Regen (letzte Stunde) in mm/h:" << (int)incoming[1] << endl;
cout << "Windgeschwindigkeit in m/s:" << setprecision (2) << windgeschw*0.0179 << endl;
cout << "Windrichtung (Grad):";
if (windgeschw != 0)
{
cout << (int)incoming[2]*360/256 << richtung[(incoming[2]+8) >> 4] << endl;
}
else
{
cout << "unbekannt (zu wenig Wind)" << endl;
}
cout << "Luftdruck in hPa:" << setprecision (0) << baro[incoming[3]] << endl;
cout << "Radioaktivität in µSv/h:" << setprecision (2) << incoming[4]*(2.5/255) << endl;
cout << "Lichtintensität in Lux:" << setprecision (0) << lux[incoming[5]] << endl;
cout << "Luftfeuchte in %:" << setprecision (0) << hyg[incoming[6]] << endl;
cout << "Temperatur in °C:" << setprecision (1) << kty[incoming[7]] << endl;
cout << "Laufzeit:" << setw(2) << setfill ('0') << h << "." << m << ":" << s << endl;
cout.flags (old_flags);
}
int main(int argc, char**argv)
{
const string program_name = argv[0];
/*
const string basedir = string (program_name, 0, program_name.rfind ('/'));
LiesTabelle (basedir + "kty.tab", kty);
LiesTabelle (basedir + "hyg.tab", hyg);
LiesTabelle (basedir + "lux.tab", lux);
LiesTabelle (basedir + "baro.tab", baro);
*/
// Schnittstelle oeffnen: lesen+schreiben, wird nicht unser
// "controlling tty", nicht-blockierend
int port_fd = open (default_device, O_RDWR | O_NOCTTY | O_NONBLOCK);
if (port_fd == -1)
{
my_perror ("Fehler beim Oeffnen des seriellen Ports");
return 1;
}
// Platz fuer Einstellungen des seriellen Ports
struct termios saved_settings, our_settings;
// aktuelle Einstellungen des Ports abfragen
if (tcgetattr (port_fd, &saved_settings) != 0)
{
my_perror ("Fehler beim Abfragen der Portparameter");
return 1;
}
// Einstellungen kopieren
our_settings = saved_settings;
// Eingabe-Geschwindigkeit setzen
cfsetispeed (&our_settings, B2400);
// Ausgabe-Geschwindigkeit setzen (ist das notwendig?)
cfsetospeed (&our_settings, B2400);
// raw-Modus anschalten -> 8Bit, keine Paritaet, 1 Stopbit, keine
// Flusskontrolle, keine Verarbeitung spezieller Zeichen
cfmakeraw (&our_settings);
// Einstellungen uebernehmen, jetzt!
if (tcsetattr (port_fd, TCSANOW, &our_settings) != 0)
{
my_perror ("Fehler beim Setzen der Portparameter");
return 1;
}
// jetzt wollen wir noch den DTR anmachen
int port_status;
if (ioctl (port_fd, TIOCMGET, &port_status) != 0)
{
my_perror ("Fehler beim Abfragen des Portstatus");
return 1;
}
// DTR setzen, falls noch nicht gesetzt
if ((port_status | TIOCM_DTR) == 0)
{
// FIXME: Geht nicht, ich bekomme "bad address"
// zum Glueck ist DTR an...
if (ioctl (port_fd, TIOCMSET, port_status|TIOCM_DTR) != 0)
{
my_perror ("Fehler beim Setzen des Portstatus");
//cerr << hex << "alter Status: " << port_status << ", neuer: " << (port_status | TIOCM_DTR) << endl;
return 1;
}
}
struct timeval timeout;
timeout.tv_sec = timeout_sec;
timeout.tv_usec = timeout_usec;
/* Eingangs-Puffer */
unsigned char incoming[14];
int inpos = 0;
for (inpos = 0; inpos < 14; inpos++)
{
fd_set read_set;
FD_ZERO (&read_set);
FD_SET (port_fd, &read_set);
// warten auf Daten, mit Timeout
// Achtung: Die Struktur timeout wird modifiziert und enthaelt
// nach dem Aufruf die Rest-Zeit. Das ist nicht portabel auf
// andere Unices.
int status = select (port_fd+1, &read_set, 0L, 0L, &timeout);
if (status == -1)
{
my_perror ("Fehler beim Warten auf Daten");
return 1;
}
if (status == 0)
{
cerr << "Timeout beim Warten auf Daten. Breche ab." << endl;
break;
}
// Daten sind da -> lesen wir sie, bis max. Pufferende
ssize_t bytes_read = read (port_fd, incoming, 14-inpos);
if (bytes_read == -1)
{
my_perror ("Fehler beim Lesen der Daten");
return 1;
}
inpos += bytes_read;
}
// Puffer wurde gelesen
if (inpos >= 14)
{
Auswertung (incoming);
}
else
{
cout << inpos << endl;
}
// Alte Einstellungen wiederherstellen
/* FIXME: Geht nicht, ich bekomme "bad address"
if (ioctl (port_fd, TIOCMSET, port_status) != 0)
{
my_perror ("Fehler beim Wiederherstellen des Portstatus");
return 1;
}
*/
if (tcsetattr (port_fd, TCSANOW, &saved_settings) != 0)
{
my_perror ("Fehler beim Wiederherstellen der Portparameter");
return 1;
}
close (port_fd);
return 0;
}
const float kty[256] = {
-27.5, -27.0, -26.0, -25.5, -24.5, -24.0, -23.5, -22.5,
-22.0, -21.5, -20.5, -20.0, -19.5, -18.5, -18.0, -17.5,
-17.0, -16.0, -15.5, -15.0, -14.0, -13.5, -13.0, -12.5,
-11.5, -11.0, -10.5, -9.5, -9.0, -8.5, -8.0, -7.5,
-6.5, -6.0, -5.5, -5.0, -4.0, -3.5, -3.0, -2.5,
-2.0, -1.0, -0.5, 0.0, 0.5, 1.0, 2.0, 2.5,
3.0, 3.5, 4.0, 4.5, 5.5, 6.0, 6.5, 7.0,
7.5, 8.0, 8.5, 9.5, 10.0, 10.5, 11.0, 11.5,
12.0, 12.5, 13.0, 14.0, 14.5, 15.0, 15.5, 16.0,
16.5, 17.0, 17.5, 18.0, 18.5, 19.0, 20.0, 20.5,
21.0, 21.5, 22.0, 22.5, 23.0, 23.5, 24.0, 24.5,
25.0, 25.5, 26.0, 26.5, 27.0, 27.5, 28.0, 28.5,
29.5, 30.0, 30.5, 31.0, 31.5, 32.0, 32.5, 33.0,
33.5, 34.0, 34.5, 35.0, 35.5, 36.0, 36.5, 37.0,
37.5, 38.0, 38.5, 39.0, 39.5, 40.0, 40.5, 41.0,
41.5, 42.0, 42.5, 43.0, 43.5, 43.5, 44.0, 44.5,
45.0, 45.5, 46.0, 46.5, 47.0, 47.5, 48.0, 48.5,
49.0, 49.5, 50.0, 50.5, 51.0, 51.5, 52.0, 52.5,
53.0, 53.5, 53.5, 54.0, 54.5, 55.0, 55.5, 56.0,
56.5, 57.0, 57.5, 58.0, 58.5, 59.0, 59.0, 59.5,
60.0, 60.5, 61.0, 61.5, 62.0, 62.5, 63.0, 63.5,
64.0, 64.0, 64.5, 65.0, 65.5, 66.0, 66.5, 67.0,
67.5, 68.0, 68.0, 68.5, 69.0, 69.5, 70.0, 70.5,
71.0, 71.0, 71.5, 72.0, 72.5, 73.0, 73.5, 74.0,
74.5, 74.5, 75.0, 75.5, 76.0, 76.5, 77.0, 77.5,
77.5, 78.0, 78.5, 79.0, 79.5, 80.0, 80.0, 80.5,
81.0, 81.5, 82.0, 82.5, 82.5, 83.0, 83.5, 84.0,
84.5, 85.0, 85.0, 85.5, 86.0, 86.5, 87.0, 87.0,
87.5, 88.0, 88.5, 89.0, 89.5, 89.5, 90.0, 90.5,
91.0, 91.5, 91.5, 92.0, 92.5, 93.0, 93.5, 93.5,
94.0, 94.5, 95.0, 95.5, 95.5, 96.0, 96.5, 97.0,
97.5, 97.5, 98.0, 98.5, 99.0, 99.0, 99.5, 100.0
};
const float hyg[256] = {
100, 100, 100, 100, 100, 100, 100, 100,
100, 100, 100, 100, 100, 100, 100, 100,
100, 100, 100, 100, 100, 100, 100, 100,
100, 100, 100, 100, 100, 100, 100, 100,
100, 99, 99, 99, 98, 98, 98, 97,
97, 96, 96, 96, 95, 95, 95, 94,
94, 94, 93, 93, 92, 92, 92, 91,
91, 91, 90, 90, 89, 89, 89, 88,
88, 88, 87, 87, 86, 86, 86, 85,
85, 85, 84, 84, 83, 83, 83, 82,
82, 81, 81, 81, 80, 80, 79, 79,
79, 78, 78, 77, 77, 77, 76, 76,
75, 75, 75, 74, 74, 73, 73, 72,
72, 72, 71, 71, 70, 70, 69, 69,
69, 68, 68, 67, 67, 66, 66, 66,
65, 65, 64, 64, 63, 63, 62, 62,
62, 61, 61, 60, 60, 59, 59, 58,
58, 57, 57, 57, 56, 56, 55, 55,
54, 54, 53, 53, 52, 52, 51, 51,
50, 50, 49, 49, 48, 48, 47, 47,
46, 46, 45, 45, 44, 44, 43, 43,
42, 42, 41, 41, 40, 40, 39, 39,
38, 37, 37, 36, 36, 35, 35, 34,
34, 33, 32, 32, 31, 31, 30, 30,
29, 28, 28, 27, 27, 26, 25, 25,
24, 24, 23, 22, 22, 21, 20, 20,
19, 18, 18, 17, 16, 16, 15, 15,
14, 13, 12, 12, 11, 10, 10, 9,
8, 7, 7, 6, 5, 5, 4, 3,
2, 1, 1, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0
};
const float lux[256] = {
0, 0, 10, 30, 50, 80, 100, 100,
100, 100, 110, 110, 110, 120, 130, 140,
150, 160, 170, 180, 190, 200, 200, 220,
230, 240, 250, 270, 290, 300, 330, 350,
380, 400, 430, 450, 470, 490, 510, 530,
550, 570, 590, 610, 630, 700, 750, 850,
980, 1150, 1300, 1500, 1700, 1900, 2600, 3200,
4100, 4500, 4700, 5200, 5700, 6400, 7300, 8000,
8400, 8900, 9300, 9700, 10000, 10500, 10800, 11000,
11200, 11400, 11700, 11900, 12300, 12400, 12600, 12800,
13100, 13700, 14300, 14900, 15300, 15900, 16600, 17000,
17500, 18000, 18500, 19000, 19600, 20100, 20800, 21400,
22000, 22700, 23300, 23900, 24500, 25100, 25900, 26500,
27000, 27600, 28200, 28800, 29400, 30000, 30600, 31200,
31800, 32500, 33100, 33700, 34300, 35000, 35600, 36200,
36800, 37500, 38100, 38700, 39300, 40000, 40500, 41000,
41500, 42000, 42500, 43000, 43500, 44000, 44500, 45000,
45500, 46000, 46500, 47000, 47500, 48000, 48500, 49000,
49500, 50000, 50300, 50600, 50900, 51200, 51500, 51800,
52100, 52400, 52700, 53000, 53300, 53600, 53900, 54200,
54500, 54800, 55100, 55400, 55700, 56000, 56300, 56600,
56900, 57200, 57500, 57800, 58100, 58400, 58700, 59000,
59300, 59600, 59900, 60200, 60500, 60800, 61100, 61400,
61700, 62000, 62300, 62600, 62900, 63200, 63500, 63800,
64100, 64400, 64700, 65000, 65300, 65600, 65900, 66200,
66500, 66800, 67100, 67400, 67700, 68000, 68300, 68600,
68900, 69200, 69500, 69800, 70100, 70400, 70700, 71000,
71300, 71600, 71600, 71900, 72200, 72500, 72800, 73100,
73400, 73700, 74000, 74000, 74300, 74600, 74900, 75200,
75500, 75800, 76100, 76400, 76700, 77000, 77300, 77600,
77900, 78200, 78500, 78800, 79100, 79400, 79700, 80000,
80300, 80600, 80900, 81200, 81500, 81800, 82100, 85000
};
const float baro[256] = {
815, 816, 817, 818, 819, 820, 821, 822,
823, 824, 825, 826, 827, 828, 829, 830,
831, 832, 833, 834, 835, 836, 837, 838,
839, 840, 841, 842, 843, 844, 845, 846,
847, 848, 849, 850, 851, 852, 853, 854,
855, 856, 857, 858, 859, 860, 861, 862,
863, 864, 865, 866, 867, 868, 869, 870,
871, 872, 873, 874, 875, 876, 877, 878,
879, 880, 881, 882, 883, 884, 885, 886,
887, 888, 889, 890, 891, 892, 893, 894,
895, 896, 897, 898, 899, 900, 901, 902,
903, 904, 905, 906, 907, 908, 909, 910,
911, 912, 913, 914, 915, 916, 917, 918,
919, 920, 921, 922, 923, 924, 925, 926,
927, 928, 929, 930, 931, 932, 933, 934,
935, 936, 937, 938, 939, 940, 941, 942,
943, 944, 945, 946, 947, 948, 949, 950,
951, 952, 953, 954, 955, 956, 957, 958,
959, 960, 961, 962, 963, 964, 965, 966,
967, 968, 969, 970, 971, 972, 973, 974,
975, 976, 977, 978, 979, 980, 981, 982,
983, 984, 985, 986, 987, 988, 989, 990,
991, 992, 993, 994, 995, 996, 997, 998,
999, 1000, 1001, 1002, 1003, 1004, 1005, 1006,
1007, 1008, 1009, 1010, 1011, 1012, 1013, 1014,
1015, 1016, 1017, 1018, 1019, 1020, 1021, 1022,
1023, 1024, 1025, 1026, 1027, 1028, 1029, 1030,
1031, 1032, 1033, 1034, 1035, 1036, 1037, 1038,
1039, 1040, 1041, 1042, 1043, 1044, 1045, 1046,
1047, 1048, 1049, 1050, 1051, 1052, 1053, 1054,
1055, 1056, 1057, 1058, 1059, 1060, 1061, 1062,
1063, 1064, 1065, 1066, 1067, 1068, 1069, 1070
};
/* vim:ts=4:sw=4:ai:si:nocindent
*/
Detected encoding: ANSI (CP1252) | 4
|
|