/* TENKI (jap. <Wetter>) liest Datenbytes vom Conrad-Telemetrie-Empfnger
* an COM2 und stellt eine einfache HTML-Seite mit den Wetterdaten bereit
*
* Das Programm ist als Win32-Konsolen-Anwendung in Borland C 5 geschrieben,
* bentigt 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 umfat 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) Radioaktivitt [100Sv/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 Zhler-/Frequenzmesserwertes Windgeschw.
11 Low-Byte des Zhler-/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 Megren
der von uns angebotenen Sensoren erfolgt in den meisten Fllen durch
Tabellendateien.
Die Tabellen bercksichtigen eventuelle Nichtlinearitten der Sensorkennlinien
und nehmen Rundungen vor.
Byte 12 enthlt im MSB das Stopflag (kennzeichnet den letzen Datenrahmen
und die Stoppzeit nach dem Low-High-bergang am Triggereingang).
Byte 13 enthlt im MSB das Zeitformatflag der Stoppuhr:
0 = Minuten:Sekunden:Hundertstel
1 = Stunden:Minuten:Sekunden
Luft die Stoppuhr lnger als eine Stunde, erfolgt automatisch das
Umschalten des Zeitformates. Luft die Stoppuhr lnger als 24 Stunden,
rollt der Stundenwert nach 23 auf 0. Dies kann zum Zhlen von Tagen
genutzt werden.
*/
const FrameGap=300U; //Millisekunden Mindest-Lcke
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-Sdost","Sdost","Sd-Sdost",
"Sd","Sd-Sdwest","Sdwest","West-Sdwest",
"West","West-Nordwest","Nordwest","Nord-Nordwest"};
// Windgeschwindigkeit vorberechnen:
// Leider hinterlt der Sender bei stehendem Flgelrad
// 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,"\nRadioaktivitt: %.2f Sv/h",incoming[4]*(2.5/255));
fprintf(fh,"\nLichtintensitt: %.0f Lux",lux[incoming[5]]);
fprintf(fh,"\nLuftfeuchte: %.0f %%",hyg[incoming[6]]);
fprintf(fh,"\nTemperatur: %.1f C",kty[incoming[7]]);
fprintf(fh,"\n\nBeim Empfnger 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;
}
Vorgefundene Kodierung: UTF-8 | 0
|