Funk wetterstations Analyse Programm
Version vom 15. September 2010, 19:51 Uhr von Biff (Diskussion | Beiträge) (HTML-Format aufgeräumt, typo)
// ################################################################################
// # #
// # Daten Analyse und Programm Erstellung: #
// # Copyright (c) 2009-2010 - Michael Schultz <ethersex@keyb.de> #
// # Mit viel unterstuetzung/Geduld von: stesie, veyron und DanielW #
// # #
// # This program is free software; you can redistribute it and/or modify it #
// # under the terms of the GNU General Public License (either version 2 or #
// # version 3) as published by the Free Software Foundation. #
// # #
// # 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. #
// # #
// # For more information on the GPL, please go to: #
// # http://www.gnu.org/copyleft/gpl.html #
// # #
// # #
// # Wetter-Funk-Daten Analyse Programm für Wetter Station der Firma #
// # Krippl Watches GmbH -- http://www.produktservice.info #
// # Protokoll analyse siehe: #
// # http://www.ethersex.de/index.php/Funk-wetterstations-protokoll #
// # #
// ################################################################################
// Logging Destination Host: 10.0.0.77 on Port 95
#define PRESCALER 1024
#define NS_PER_TICK (PRESCALER * 1000000UL / F_CPU * 1000)
#define US_TO_TICKS(n) ((n) * 1000UL / NS_PER_TICK)
// debug ausgabe 0 = keine debug meldungen, 1 = ein bischen merh, und 2 für Timing ausgaben
#define WEATHERVERBOSE 2
uint16_t Count1;
uint16_t Count2;
#if WEATHERVERBOSE >= 2
uint8_t WordBitTiming[300];
uint16_t WordBitTimingPos;
#endif
// Timing @16mhz: Timer Count Timer C. Hex Decode
uint8_t Time0 = US_TO_TICKS(1920); // L space 1920 bis 1999us 30-31,2 0x1E 0x1F 0
uint8_t Time1 = US_TO_TICKS(3990); // H space 3990 bis 4049us 62,3-63,2 0x3E 0x3F 1
uint8_t Time2 = US_TO_TICKS(2060); // End-l space 2060 bis 2089us 32,1-32,6 0x20 0x21 2
uint8_t Time3 = US_TO_TICKS(4130); // End-h space 4130 bis 4169us 64,5-65,1 0x40 0x41 3
uint8_t Time4 = US_TO_TICKS(8890); // Start space 8890 bis 8939us 138,9-139,6 0x8A 0x8C 4
uint8_t Time5 = US_TO_TICKS(360); // End- pulse 360 bis 369us 5,6-5,7 0x05 5
uint8_t Time6 = US_TO_TICKS(440); // _ pulse 440 bis 519us 6,8-8,1 0x06 0x08 6
// Pause
//
uint8_t BitPos = 0; // Bit Position innerhalb eines 36 bit worts (1 bis 37)
uint8_t WordCound = 0; // Daten Wort Count (1 bis 9)
uint8_t WordByte[45]; // 1 Data Word = 5 Byte / Max 8 Data Words
uint8_t WordBytePos = 0; // Byte Pos in WordByte
uint8_t MatchPos = 0; // meist vorkommene datenwort position im telegram
uint8_t MatchCount = 0; // wie viel treffer hatte dieses meist vorkommende telegram
//
uint16_t Temp = 0; // Temperatur Wert (-)76,8 bis (+)127,9 °C, Vorzeichen wird erst bei der ausgabe gesetzt.
uint16_t Feuchte = 0; // Luftfeuchte Wert 20-99 %
uint8_t timer_0 = 0; // Timer Wert für zeitbestimming zwichen 2 Pegel änderungen (Interrupts)
uint8_t Temp1 = 0; // Temperatur wert, einer stelle --> 0,n °C
uint8_t Temp10 = 0; // Temperatur wert, zener stelle --> n,0 °C
//
uint8_t Analysis[10] ; // Daten Analyse array
// Analysis[0 bis 7] Treffer der Daten Packets Übereinstimmung.
// Analysis[8] - bit(0) = 1 Daten Liegen an und können vearbeitete werden
// Analysis[8] - bit(1) = 1 Datenanalyse erfolgreich, Mindestens 3 Übereinstimmungen
// Analysis[8] - bit(2) = 1 Daten sind Verarbeitet und können gesendet werden
// Analysis[9] Array Positions Counter fuer analyse
char YearMonth[13][4] = {"---", "Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"};
CONTROL_START
ON STARTUP DO
Analysis[8] |= (1 << 2); // nach start einmal ausgabe, um zu schauen wann das ding gebootet ist...
_TCCR0_PRESCALE |= _BV(CS02); // TCCR0B(CS02)=1
_TCCR0_PRESCALE &= ~_BV(CS01); // TCCR0B(CS01)=0
_TCCR0_PRESCALE |= _BV(CS00); // TCCR0B(CS00)=1
_EIMSK |= _BV(INT0); // EIMSK(INT0) = 1 Interrupt, Input Data on INT0 / PD2
_EICRA &= ~_BV(ISC01); // EICRA(ISC01) = 0 interrupt on any edge, asyncronously
_EICRA |= _BV(ISC00); // EICRA(ISC00) = 1 interrupt on any edge, asyncronously
_TIMSK_TIMER0 |= _BV(TOIE0); // TIMSK0(TOIE0) = 1 Interrupt on Timer Overflow aktivieren
TCP_CONNECT(10.0.0.77, 95, message_handler);
END
TCP_HANDLER_PERSIST(message_handler)
for (;;) {
// Analysis[8] - bit(2) = 1 Daten sind Verarbeitet und können gesendet werden
if ( Analysis[8] & ( 1 << 2 ) ) {
// Lösche ale Analysis Counter
for (Count1 = 0; Count1 < 8; Count1 ++) Analysis[ (Count1) ] = 0 ;
// wie oft matcht welsches telegram mit allen anderen 8 telegrammen
for (Count1 = 0; Count1 < 8; Count1 ++)
for (Count2 = 0; Count2 < 8; Count2 ++)
if (memcmp(&WordByte[ (Count1) * 5 ], &WordByte[ ( Count2 + 1 ) * 5], 5) == 0)
{ Analysis[ (Count1) ] ++ ; }
// nim nur das telegram mit der größten anzahl an treffer
for (Count1 = 8; Count1 > 1; Count1 --)
for (Count2 = 0; Count2 < 8; Count2 ++)
if ( Analysis[ (Count2) ] == Count1 ) {
MatchPos = Count2 ;
MatchCount = Count1 ;
WordByte[40] = WordByte[ ( MatchPos * 5 ) ] ;
WordByte[41] = WordByte[ ( MatchPos * 5 ) + 1 ] ;
WordByte[42] = WordByte[ ( MatchPos * 5 ) + 2 ] ;
WordByte[43] = WordByte[ ( MatchPos * 5 ) + 3 ] ;
WordByte[44] = WordByte[ ( MatchPos * 5 ) + 4 ] ;
}
// binär analyse der temperatur
Temp = 0 ;
if ( WordByte[41] & ( 1 << 3 ) ) { Temp = Temp + 1 ; }
if ( WordByte[41] & ( 1 << 2 ) ) { Temp = Temp + 2 ; }
if ( WordByte[41] & ( 1 << 1 ) ) { Temp = Temp + 4 ; }
if ( WordByte[41] & ( 1 << 0 ) ) { Temp = Temp + 8 ; }
if ( WordByte[42] & ( 1 << 7 ) ) { Temp = Temp + 16 ; }
if ( WordByte[42] & ( 1 << 6 ) ) { Temp = Temp + 32 ; }
if ( WordByte[42] & ( 1 << 5 ) ) { Temp = Temp + 64 ; }
if ( WordByte[42] & ( 1 << 4 ) ) { Temp = Temp + 128 ; }
if ( WordByte[42] & ( 1 << 3 ) ) { Temp = Temp + 256 ; }
if ( WordByte[42] & ( 1 << 2 ) ) { Temp = Temp + 512 ; }
if ( WordByte[42] & ( 1 << 1 ) ) { Temp = Temp + 1024 ; }
Temp10=( Temp / 10 );
Temp1=( Temp - ( ( Temp / 10 ) * 10 ) );
// binär analyse der luftfeuchtigkeit
Feuchte = 0 ;
if ( WordByte[43] & ( 1 << 7 ) ) { Feuchte = Feuchte + 1 ; }
if ( WordByte[43] & ( 1 << 6 ) ) { Feuchte = Feuchte + 2 ; }
if ( WordByte[43] & ( 1 << 5 ) ) { Feuchte = Feuchte + 4 ; }
if ( WordByte[43] & ( 1 << 4 ) ) { Feuchte = Feuchte + 8 ; }
if ( WordByte[43] & ( 1 << 3 ) ) { Feuchte = Feuchte + 10 ; }
if ( WordByte[43] & ( 1 << 2 ) ) { Feuchte = Feuchte + 20 ; }
if ( WordByte[43] & ( 1 << 1 ) ) { Feuchte = Feuchte + 40 ; }
if ( WordByte[43] & ( 1 << 0 ) ) { Feuchte = Feuchte + 80 ; }
// syslog format, initial <Priority Facility>
TCP_SEND("<27>%s %02d %02d:%02d:%02d %s wheather: code:", &YearMonth[CLOCK_MONTH()], CLOCK_DAY(), CLOCK_HOUR(), CLOCK_MIN(), CLOCK_SEC(), CONF_HOSTNAME);
if ( WordByte[40] & ( 1 << 3 ) ) { TCP_SEND("1"); } else { TCP_SEND("0"); }
if ( WordByte[40] & ( 1 << 2 ) ) { TCP_SEND("1-"); } else { TCP_SEND("0-"); }
if ( WordByte[40] & ( 1 << 7 ) ) { TCP_SEND("1"); } else { TCP_SEND("0"); }
if ( WordByte[40] & ( 1 << 6 ) ) { TCP_SEND("1"); } else { TCP_SEND("0"); }
if ( WordByte[40] & ( 1 << 5 ) ) { TCP_SEND("1"); } else { TCP_SEND("0"); }
if ( WordByte[40] & ( 1 << 4 ) ) { TCP_SEND("1-"); } else { TCP_SEND("0-"); }
if ( WordByte[40] & ( 1 << 1 ) ) { TCP_SEND("1"); } else { TCP_SEND("0"); }
if ( WordByte[40] & ( 1 << 0 ) ) { TCP_SEND("1-"); } else { TCP_SEND("0-"); }
if ( WordByte[41] & ( 1 << 7 ) ) { TCP_SEND("1"); } else { TCP_SEND("0"); }
if ( WordByte[41] & ( 1 << 6 ) ) { TCP_SEND("1"); } else { TCP_SEND("0"); }
if ( WordByte[41] & ( 1 << 5 ) ) { TCP_SEND("1"); } else { TCP_SEND("0"); }
TCP_SEND(" temp:");
if ( WordByte[42] & ( 1 << 0 ) ) { TCP_SEND("-"); } else { TCP_SEND("+"); }
TCP_SEND("%d.%d hum:%d%% manu:", Temp10, Temp1, Feuchte);
if ( WordByte[41] & ( 1 << 4 ) ) { TCP_SEND("1"); } else { TCP_SEND("0"); }
TCP_SEND(" Match:%d/%d", MatchPos, MatchCount);
TCP_SEND(" data:%02x%02x%02x%02x%02x\n", WordByte[40], WordByte[41], WordByte[42], WordByte[43], WordByte[44]);
#if WEATHERVERBOSE == 1
TCP_SEND("00 --> %02x%02x%02x%02x%02x Match:%d\n", WordByte[0], WordByte[1], WordByte[2], WordByte[3], WordByte[4], Analysis[0]);
TCP_SEND("01 --> %02x%02x%02x%02x%02x Match:%d\n", WordByte[5], WordByte[6], WordByte[7], WordByte[8], WordByte[9], Analysis[1]);
TCP_SEND("02 --> %02x%02x%02x%02x%02x Match:%d\n", WordByte[10], WordByte[11], WordByte[12], WordByte[13], WordByte[14], Analysis[2]);
TCP_SEND("03 --> %02x%02x%02x%02x%02x Match:%d\n", WordByte[15], WordByte[16], WordByte[17], WordByte[18], WordByte[19], Analysis[3]);
TCP_SEND("04 --> %02x%02x%02x%02x%02x Match:%d\n", WordByte[20], WordByte[21], WordByte[22], WordByte[23], WordByte[24], Analysis[4]);
TCP_SEND("05 --> %02x%02x%02x%02x%02x Match:%d\n", WordByte[25], WordByte[26], WordByte[27], WordByte[28], WordByte[29], Analysis[5]);
TCP_SEND("06 --> %02x%02x%02x%02x%02x Match:%d\n", WordByte[30], WordByte[31], WordByte[32], WordByte[33], WordByte[34], Analysis[6]);
TCP_SEND("07 --> %02x%02x%02x%02x%02x Match:%d\n", WordByte[35], WordByte[36], WordByte[37], WordByte[38], WordByte[39], Analysis[7]);
TCP_SEND("Out --> %02x%02x%02x%02x%02x\n", WordByte[40], WordByte[41], WordByte[42], WordByte[43], WordByte[44]);
TCP_SEND("\n");
TCP_SEND("\n");
#endif
#if WEATHERVERBOSE == 2
TCP_SEND("\nHexData: ");
for (Count1 = 0; Count1 < 300; Count1 ++) {
if ( WordBitTiming[Count1] >= Time4 && WordBitTiming[Count1] <= ( Time4 + 5 ) ) {
TCP_SEND("\nHexData: %02x", WordBitTiming[Count1]);
} else if ( WordBitTiming[Count1] != 0 ) {
TCP_SEND("%02x", WordBitTiming[Count1]);
WordBitTiming[Count1] = 0;
}
}
TCP_SEND("\n");
#endif
Analysis[8] &= ~(1 << 2); // deaktivieren der Daten sendung
for (Count1 = 0; Count1 < 45; Count1 ++) {
WordByte[Count1] = 0;
}
}
Analysis[9] = 0;
PT_YIELD(pt);
}
TCP_HANDLER_END();
CONTROL_END
// ###############################################################################################################################
ISR(INT0_vect) {
timer_0 = TCNT0;
#if WEATHERVERBOSE >= 2
WordBitTiming[WordBitTimingPos] = timer_0 ;
if ( BitPos == 0 && WordCound == 0 ) {
} else {
WordBitTimingPos ++ ;
}
if ( WordBitTimingPos >= 300 ) {
WordBitTimingPos = 300 ;
}
#endif
WordBytePos=(( BitPos / 8 ) + ( WordCound * 5 ));
if ( WordBytePos >= 40 ) {
BitPos = 0 ;
WordCound = 0 ;
}
if ( timer_0 >= Time6 && timer_0 <= ( Time6 + 3 ) ) { // _ (puls)
#if WEATHERVERBOSE >= 2
WordBitTimingPos -- ;
#endif
} else if ( timer_0 == Time0 || timer_0 == ( Time0 + 1 ) ) { // L 0 (L - Bit - Normal)
WordByte[WordBytePos] &= ~(1 << ( 7 - (BitPos % 8))); // WordByte[n] = 0;
BitPos ++ ;
} else if ( timer_0 == Time1 || timer_0 == ( Time1 + 1 ) ) { // H 1 (H - Bit - Normal)
WordByte[WordBytePos] |= 1 << ( 7 - (BitPos % 8)); // WordByte[n] = 1;
BitPos ++ ;
} else if ( timer_0 == Time2 || timer_0 == ( Time2 + 1 ) ) { // End-l 2 (Ende Datenwort L)
WordByte[WordBytePos] &= ~(1 << ( 7 - (BitPos % 8))); // WordByte[n] = 0;
BitPos ++ ;
} else if ( timer_0 == Time3 || timer_0 == ( Time3 + 1 ) ) { // End-h 3 (Ende Datenwort H)
WordByte[WordBytePos] |= 1 << ( 7 - (BitPos % 8)); // WordByte[n] = 1;
BitPos ++ ;
} else if ( timer_0 >= Time4 && timer_0 <= ( Time4 + 5 ) ) { // Start 4 (Start Datenwort)
if ( BitPos != 1 ) {
WordCound ++ ;
WordByte[ WordBytePos ] = 0 ;
WordByte[ WordBytePos + 1 ] = 0 ;
WordByte[ WordBytePos + 2 ] = 0 ;
WordByte[ WordBytePos + 3 ] = 0 ;
WordByte[ WordBytePos + 4 ] = 0 ;
}
BitPos = 0;
} else { // ? 8 (Nicht Erkanntes Timing)
BitPos ++ ;
}
TCNT0 = 0;
}
//
// L 0 (L - Bit) 30
// H 1 (H - Bit) 62
// End-l 2 (Ende Datenwort L) 32
// End-h 3 (Ende Datenwort H) 64
// Start 4 (Start Datenwort) 138
// End- 5 (Daten Sendung Ende) 5
// _ 6 (puls) 6
// Pause 7 (Timer Overflow)
// ? 8 (Nicht Erkanntes Timing)
//
// uint8_t BitPos = 0; // Bit Position innerhalb eines 36 bit worts (0 bis 36)
// uint8_t WordCound = 0; // Daten Wort Count (0 bis 7)
// uint8_t WordByte[40]; // 1 Data Word = 5 Byte / Max 8 Data Words
//
// WordByte[0] WordByte[1] WordByte[2] WordByte[3] WordByte[4]
//
// 0 0 1 1 2 2 3 3 4 4
// 5 D 0 0 4 8 E 4 7 0
// 0101 1101 0000 0000 0100 1000 1110 0100 0111 0000
// RRRR CCBB ???S TTTT TTTT TTTT LLLL LLLL cccc ----
//
// ###############################################################################################################################
ISR(TIMER0_OVF_vect) {
if ( WordCound >= 3 ) {
// zeitüberschreitung, warscheinlich ende einer übertragung, ausgabe aktivieren
Analysis[8] |= (1 << 2);
}
TIFR0 &= ~_BV(TOV0); // TIFR0(TOV0) = 0
BitPos = 0;
WordCound = 0;
#if WEATHERVERBOSE >= 2
WordBitTimingPos = 0 ;
#endif
}
// ###############################################################################################################################
// gummi:~#
// gummi:~# while true ; do socat stdio tcp4-listen:95 ; echo "##########" ; sleep 1 ; done
//
// gummi:/usr/src/ethersex/090730_wichtel_ac:de:48:d3:99:5f/ethersex/control6#
// cd .. ; make clean ; make ; scp ethersex.bin 10.0.0.10:/var/lib/tftpboot/ACDE48D3995F ;
// cd control6/ ; echo "bootloader" | socat stdio tcp4:10.0.0.40:2701
//
// gummi:/usr/src/ethersex/090730_wichtel_ac:de:48:d3:99:5f/ethersex/control6#
// cat funk_temp_und_feuchte_daten.src | sed 's///[\ \t]*.*//g' | sed 's/^\t\+$//' | grep -v '^$'
//
// gummi:~#
// while true ; do socat stdio tcp4-listen:95 | while read Line ; do
// if [ "$(echo $Line | grep -c '^--')" = "1" ] ; then echo ; echo ; else
// echo -en "$Line" | sed 's/^_//' ; fi ; done | sed 's/\(8[bc]0[78]\)/\n\1/g' ;
// echo "##########" ; sleep 1 ; done
//
Empfangen der "Wetter"-Daten mittels Syslog-NG
Sample "/etc/syslog-ng/syslog-ng.conf" File
################################################################################
# Speicherung der "Wetter" Daten (Temp und Feuchte)
################################################################################
source src_net_t95 { tcp( ip(10.0.0.77) port(95) max_connections(1000) ); };
destination dst_file_t95 { file("/mnt/log/current/$YEAR/$MONTH/$DAY/$HOUR/$HOST/$PROGRAM/$FACILITY.$PRIORITY.log"); };
log { source(src_net_t95); destination(dst_file_t95); };
################################################################################
So sehen die Daten dann gespeichert aus:
(/mnt/log/current/2009/08/03/08/wichtel/ethersex/daemon.err.log
May 2 06:25:00 wichtel wheather: code:01-0001-00-000 temp:+24.7 hum:26% manu:0 Match:6/6 data:140ef06400
May 2 06:25:03 10.0.0.40 HexData: 1e1e3f1e3f1f1f1e1e1e1e3f3f3f1e3f3e3f3f1f1f1e1e1e3f3e1f1f3f1e1f3f3f3f20
May 2 06:25:03 10.0.0.40 HexData: 8b1e1f1f3f1e3f1e1e1e1f1f1f3e3f3f1f3f3f3e3f1e1e1e1f1f3f3f1e1e3f1f1e3f3f3f21
May 2 06:25:03 10.0.0.40 HexData: 8c1f1f1e3f1f3f1f1f1f1e1e1e3f3e3f1e3f3f3f3e1f1f1f1e1e3f3f1e1f3f1e1e3f3f3f20
May 2 06:25:03 10.0.0.40 HexData: 8b1e1e1e3f1e3f1f1e1e1e1f1f3f3f3e1f3f3f3f3f1e1e1e1e1f3f3f1f1e3f1f1f3e3f3f21
May 2 06:25:03 10.0.0.40 HexData: 8b1f1f1f3e1f3f1e1e1f1f1f1e3f3f3f1e3f3f3f3f1e1f1f1f1e3f3f1e1e3f1e1e3f3e3f20
May 2 06:25:04 10.0.0.40 HexData: 8b1e1e1e3f1e3f1f1f1e1e1e1f3f3f3f1e3f3f3f3f1f1e1e1e1e3f3f1f1f3e1f1f3f3f3e20
May 2 06:25:04 10.0.0.40 HexData: 8b1e1f1f3f1e3f1e1e1e1f1f1f3f3f3f1f3f3f3f3f1e1e1f1f1f3e3f1e1e3f1e1e3f3f3f20
May 2 06:25:04 10.0.0.40 HexData: 8b1f1e1e3f1f3e1f1f1f1e1e1e3f3e3f1e3f3f3f3f1f1f1f1e08
May 2 06:25:31 wichtel wheather: code:01-0001-00-000 temp:+24.7 hum:26% manu:1 Match:6/6 data:141ef06400
May 2 06:25:35 10.0.0.40 HexData: 1e1e3f1f3e1f1f1f1e1e3f3f3f3e1f3f3f3f3f1e1e1e1e1f3f3f1f1e3f1f1f3e3f3f41
May 2 06:25:35 10.0.0.40 HexData: 8b1e1e1e3f1e3f1f1e1e1e1e3f3f3f3f1f3e3f3f3f1e1e1f1f1f3e3f1e1e3f1e1e3f3f3f40
May 2 06:25:35 10.0.0.40 HexData: 8b1e1f1f3f1e3f1e1e1e1f1f3f3f3e3f1e3f3f3f3e1f1f1f1e1e3f3f1e1f3f1e1e3f3f3f41
May 2 06:25:35 10.0.0.40 HexData: 8c1f1f1f3f1f3f1e1f1f1f1e3f3f3f3f1e3f3f3f3f1f1e1e1e1e3f3f1f1f3e1f1f3f3f3e41
May 2 06:25:36 10.0.0.40 HexData: 8b1f1e1e3f1f3f1f1f1f1e1e3f3e3f3f1f3f3f3e3f1e1e1e1f1f3f3f1e1e3f1f1e3f3f3f41
May 2 06:25:36 10.0.0.40 HexData: 8b1e1e1e3f1e3f1f1e1e1e1f3f3f3f3f1f3f3f3f3f1e1f1f1f1e3f3f1e1e3f1e1e3f3e3f40
May 2 06:25:36 10.0.0.40 HexData: 8b1e1f1f3f1e3f1e1e1e1f1f3f3f3e3f1e3f3f3f3e1f1f1f1e1e3f3e1f1f3f1e1f3f3f3f41
May 2 06:25:36 10.0.0.40 HexData: 8c1f1f1e3f1f3f1e1f1f1f1e3f3f3f3f1e3f06