/* TENKI (jap. <Wetter>) liest Datenbytes vom Conrad-Telemetrie-Empfänger
* an COM2 und stellt eine einfache HTML-Seite mit den Wetterdaten bereit
*
* Das Programm ist als Win32-Konsolen-Anwendung in Borland C 5 geschrieben,
* benötigt keinerlei Extra-DLLs (statisch gebunden),
* erwartet vier Umrechnungstabellen festen Namens neben der "tenki.exe"
* (diese sollten durchaus als Konstanten ins Programm eingebaut werden)
* und schreibt "tenki.htm" in das aktuelle Verzeichnis.
* h#s 05/01
*/
#include <windows.h> // SetCommState, ...
#include <stdio.h> // printf, scanf, ...
#include <conio.h> // kbhit, getch
#include <string.h> // strcpy, strrchr
/*
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 FrameGap=300U; //Millisekunden Mindest-Lücke
BYTE incoming[14];
float kty[256],hyg[256],lux[256],baro[256];
char *argv0;
BOOL LeseTabelle(char *dateiname, float *puffer) {
//eine Tabelle (Datei) mit 256 float-Werten einlesen, muß neben der .EXE liegen
int i;
FILE *fh;
char fnamebuf[256];
strcpy(fnamebuf,argv0);
strcpy(strrchr(fnamebuf,'\\')+1,dateiname);
fh=fopen(fnamebuf,"rt");
if (fh) {
for (i=0; i<256; i++) {
fscanf(fh,"%f",puffer++);
}
fclose(fh);
}
return fh ? TRUE : FALSE;
}
void Vorbereitung(void) { //junbi
LeseTabelle("kty.tab",kty);
LeseTabelle("hyg.tab",hyg);
LeseTabelle("lux.tab",lux);
LeseTabelle("baro.tab",baro);
}
void Auswertung(void) {
int windgeschw;
static int letzte_windgeschw;
FILE *fh;
int h,m,s; // vom Zeit-Diagramm
char timestr[64];
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=(incoming[9]<<8)+incoming[10];
if (windgeschw==letzte_windgeschw && windgeschw<0x30) {
letzte_windgeschw=windgeschw;
windgeschw=0;
}else{
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];
}
//HTML-Datei schreiben:
fh=fopen("tenki.htm","wt");
if (!fh) {
perror("TENKI konnte HTML-Datei nicht aktualisieren!");
return;
}
fputs("<HTML><HEAD>\n",fh);
fputs("<TITLE>Gymnasium-Wetter</TITLE>\n",fh);
fputs("<meta http-equiv=\"Content-Type\" "
"content=\"text/html;CHARSET=iso-8859-1\">\n",fh);
fputs("<meta http-equiv=\"refresh\" "
"content=\"1; URL=tenki.htm\">",fh);
fputs("</HEAD><BODY>\n",fh);
fputs("<PRE>\n",fh);
GetTimeFormat(LOCALE_SYSTEM_DEFAULT,TIME_NOTIMEMARKER,
NULL,NULL,timestr,sizeof timestr);
fprintf(fh,"Uhrzeit (lokal): %s\n",timestr);
fprintf(fh,"\nRegen (letzte Stunde): %u mm/h",incoming[1]);
fprintf(fh,"\nWindgeschwindigkeit: %.2g m/s",windgeschw*0.0179);
fprintf(fh,"\nWindrichtung: ");
if (windgeschw) {
fprintf(fh,"%u ° ",incoming[2]*360/256);
fputs(richtung[(BYTE)(incoming[2]+8)>>4],fh); //mit Umlauf-Rundung
}else{
fputs("nicht angebbar",fh);
}
fprintf(fh,"\nLuftdruck: %.0f hPa",baro[incoming[3]]);
fprintf(fh,"\nRadioaktivität: %.2f µSv/h",incoming[4]*(2.5/255));
fprintf(fh,"\nLichtintensität: %.0f Lux",lux[incoming[5]]);
fprintf(fh,"\nLuftfeuchte: %.0f %%",hyg[incoming[6]]);
fprintf(fh,"\nTemperatur: %.1f °C",kty[incoming[7]]);
fprintf(fh,"\n\nBeim Empfänger ist es jetzt %02d:%02d:%02d Uhr",
h,m,s);
fputs("\n</PRE>\n",fh);
fputs("</BODY></HTML>\n",fh);
fclose(fh);
}
#pragma argsused
int main(int argc, char**argv) {
HANDLE hCom;
DCB dcb;
BYTE b;
DWORD ticks; //Millisekunden
DWORD bytesread;
int incounter=0;
puts("TENKI (h#s 05/01): generiert Web-Seite aus Wetter-Daten von COM2");
argv0=argv[0]; //Programm-Name mit Pfad
hCom=CreateFile("COM2",
GENERIC_READ|GENERIC_WRITE,
FILE_SHARE_READ|FILE_SHARE_WRITE,
NULL,
OPEN_EXISTING,
FILE_ATTRIBUTE_NORMAL,
0);
if (hCom==INVALID_HANDLE_VALUE) {
perror("TENKI konnte COM2 nicht ”ffnen");
return(1);
}
BuildCommDCB("COM2: baud=2400 parity=N data=8 stop=1",&dcb);
dcb.fDtrControl=DTR_CONTROL_ENABLE; //Stromversorgung!
if (!SetCommState(hCom,&dcb)) {
perror("TENKI konnte šbertragungsparameter nicht setzen");
}
Vorbereitung();
puts("Es geht los! Drcke irgendeine Taste zum Beenden!");
do{
ticks=GetTickCount();
ReadFile(hCom,&b,1,&bytesread,NULL);
if ((DWORD)(GetTickCount()-ticks)>(DWORD)FrameGap) {
printf("\n");
incounter=0;
}
printf("%02X ",b);
if (incounter<14) {
incoming[incounter++]=b;
if (incounter==14) {
Auswertung();
}
}
}while (!kbhit());
getch();
CloseHandle(hCom);
return 0;
}
Detected encoding: ANSI (CP1252) | 4
|
|