mirror of
https://github.com/seahu/rflink.git
synced 2025-12-10 07:57:23 +01:00
167 lines
7.5 KiB
C
167 lines
7.5 KiB
C
//#######################################################################################################
|
|
//## This Plugin is only for use with the RFLink software package ##
|
|
//## Plugin-100 AlectoV2 ##
|
|
//## > 868 MHz Plugin < ##
|
|
//#######################################################################################################
|
|
|
|
/*********************************************************************************************\
|
|
* Dit protocol zorgt voor ontvangst van Alecto weerstation buitensensoren
|
|
*
|
|
* Author : Martinus van den Broek
|
|
* Support : http://sourceforge.net/projects/rflink/
|
|
* License : This code is free for use in any open source project when this header is included.
|
|
* Usage of any parts of this code in a commercial application is prohibited!
|
|
*********************************************************************************************
|
|
* Technische informatie:
|
|
* DKW2012 Message Format: (11 Bytes, 88 bits):
|
|
* AAAAAAAA AAAABBBB BBBB__CC CCCCCCCC DDDDDDDD EEEEEEEE FFFFFFFF GGGGGGGG GGGGGGGG HHHHHHHH IIIIIIII
|
|
* Temperature Humidity Windspd_ Windgust Rain____ ________ Winddir Checksum
|
|
* A = start/unknown, first 8 bits are always 11111111
|
|
* B = Rolling code
|
|
* C = Temperature (10 bit value with -400 base)
|
|
* D = Humidity
|
|
* E = windspeed (* 0.3 m/s, correction for webapp = 3600/1000 * 0.3 * 100 = 108))
|
|
* F = windgust (* 0.3 m/s, correction for webapp = 3600/1000 * 0.3 * 100 = 108))
|
|
* G = Rain ( * 0.3 mm)
|
|
* H = winddirection (0 = north, 4 = east, 8 = south 12 = west)
|
|
* I = Checksum, calculation is still under investigation
|
|
*
|
|
* WS3000 and ACH2010 systems have no winddirection, message format is 8 bit shorter
|
|
* Message Format: (10 Bytes, 80 bits):
|
|
* AAAAAAAA AAAABBBB BBBB__CC CCCCCCCC DDDDDDDD EEEEEEEE FFFFFFFF GGGGGGGG GGGGGGGG HHHHHHHH
|
|
* Temperature Humidity Windspd_ Windgust Rain____ ________ Checksum
|
|
*
|
|
* --------------------------------------------------------------------------------------------
|
|
* DCF Time Message Format: (NOT DECODED!, we already have time sync through webapp)
|
|
* AAAAAAAA BBBBCCCC DDDDDDDD EFFFFFFF GGGGGGGG HHHHHHHH IIIIIIII JJJJJJJJ KKKKKKKK LLLLLLLL MMMMMMMM
|
|
* 11 Hours Minutes Seconds Year Month Day ? Checksum
|
|
* B = 11 = DCF
|
|
* C = ?
|
|
* D = ?
|
|
* E = ?
|
|
* F = Hours BCD format (7 bits only for this byte, MSB could be '1')
|
|
* G = Minutes BCD format
|
|
* H = Seconds BCD format
|
|
* I = Year BCD format (only two digits!)
|
|
* J = Month BCD format
|
|
* K = Day BCD format
|
|
* L = ?
|
|
* M = Checksum
|
|
\*********************************************************************************************/
|
|
#define DKW2012_MIN_PULSECOUNT 164
|
|
#define DKW2012_MAX_PULSECOUNT 176
|
|
#define ACH2010_MIN_PULSECOUNT 160 // reduce this value (144?) in case of bad reception
|
|
#define ACH2010_MAX_PULSECOUNT 160
|
|
|
|
#ifdef PLUGIN_100
|
|
|
|
uint8_t Plugin_100_ProtocolAlectoCRC8( uint8_t *addr, uint8_t len);
|
|
|
|
boolean Plugin_100(byte function, char *string) {
|
|
if (!(((RawSignal.Number >= ACH2010_MIN_PULSECOUNT) && (RawSignal.Number <= ACH2010_MAX_PULSECOUNT)) || ((RawSignal.Number >= DKW2012_MIN_PULSECOUNT) && (RawSignal.Number <= DKW2012_MAX_PULSECOUNT)))) return false;
|
|
|
|
byte c=0;
|
|
byte rfbit;
|
|
byte data[10];
|
|
byte msgtype=0;
|
|
byte rc=0;
|
|
byte checksum=0;
|
|
byte checksumcalc=0;
|
|
byte maxidx = 8;
|
|
//==================================================================================
|
|
if(RawSignal.Number > ACH2010_MAX_PULSECOUNT) maxidx = 9;
|
|
// Get message back to front as the header is almost never received complete for ACH2010
|
|
byte idx = maxidx;
|
|
for(byte x=RawSignal.Number; x>0; x=x-2) {
|
|
if(RawSignal.Pulses[x-1]*RAWSIGNAL_SAMPLE_RATE < 0x300) rfbit = 0x80; else rfbit = 0;
|
|
data[idx] = (data[idx] >> 1) | rfbit;
|
|
c++;
|
|
if (c == 8) {
|
|
if (idx == 0) break;
|
|
c = 0;
|
|
idx--;
|
|
}
|
|
}
|
|
//==================================================================================
|
|
checksum = data[maxidx];
|
|
checksumcalc = Plugin_100_ProtocolAlectoCRC8(data, maxidx);
|
|
|
|
msgtype = (data[0] >> 4) & 0xf; // msg type must be 5 or 10
|
|
rc = (data[0] << 4) | (data[1] >> 4); // rolling code
|
|
|
|
if (checksum != checksumcalc) return false;
|
|
if ((msgtype != 10) && (msgtype != 5)) return true; // why true?
|
|
//==================================================================================
|
|
unsigned int temp = 0;
|
|
unsigned int rain=0;
|
|
byte hum = 0;
|
|
int wdir = 0;
|
|
int wspeed = 0;
|
|
int wgust = 0;
|
|
|
|
temp = (((data[1] & 0x3) * 256 + data[2]) - 400);
|
|
hum = data[3];
|
|
wspeed = data[4] * 108;
|
|
wspeed = wspeed / 10;
|
|
wgust = data[5] * 108;
|
|
wgust = wgust / 10;
|
|
rain = (data[6] * 256) + data[7];
|
|
if (RawSignal.Number >= DKW2012_MIN_PULSECOUNT) {
|
|
wdir = (data[8] & 0xf);
|
|
}
|
|
// ----------------------------------
|
|
// Output
|
|
// ----------------------------------
|
|
sprintf(pbuffer, "20;%02X;", PKSequenceNumber++); // Node and packet number
|
|
Serial.print( pbuffer );
|
|
// ----------------------------------
|
|
if (RawSignal.Number >= DKW2012_MIN_PULSECOUNT) {
|
|
Serial.print("DKW2012;"); // Label
|
|
} else {
|
|
Serial.print("Alecto V2;"); // Label
|
|
}
|
|
sprintf(pbuffer, "ID=00%02x;", rc); // ID
|
|
Serial.print( pbuffer );
|
|
sprintf(pbuffer, "TEMP=%04x;", temp);
|
|
Serial.print( pbuffer );
|
|
sprintf(pbuffer, "HUM=%02x;", hum);
|
|
Serial.print( pbuffer );
|
|
sprintf(pbuffer, "WINSP=%04x;", wspeed);
|
|
Serial.print( pbuffer );
|
|
sprintf(pbuffer, "WINGS=%04x;", wgust);
|
|
Serial.print( pbuffer );
|
|
sprintf(pbuffer, "RAIN=%04x;", rain);
|
|
Serial.print( pbuffer );
|
|
if (RawSignal.Number >= DKW2012_MIN_PULSECOUNT) {
|
|
sprintf(pbuffer, "WINDIR=%04d;", wdir);
|
|
Serial.print( pbuffer );
|
|
}
|
|
Serial.println();
|
|
// ----------------------------------
|
|
RawSignal.Repeats=true; // suppress repeats of the same RF packet
|
|
RawSignal.Number=0; // do not process the packet any further
|
|
return true;
|
|
}
|
|
|
|
/*********************************************************************************************\
|
|
* Calculates CRC-8 checksum
|
|
* reference http://lucsmall.com/2012/04/29/weather-station-hacking-part-2/
|
|
* http://lucsmall.com/2012/04/30/weather-station-hacking-part-3/
|
|
* https://github.com/lucsmall/WH2-Weather-Sensor-Library-for-Arduino/blob/master/WeatherSensorWH2.cpp
|
|
\*********************************************************************************************/
|
|
uint8_t Plugin_100_ProtocolAlectoCRC8( uint8_t *addr, uint8_t len) {
|
|
uint8_t crc = 0;
|
|
// Indicated changes are from reference CRC-8 function in OneWire library
|
|
while (len--) {
|
|
uint8_t inbyte = *addr++;
|
|
for (uint8_t i = 8; i; i--) {
|
|
uint8_t mix = (crc ^ inbyte) & 0x80; // changed from & 0x01
|
|
crc <<= 1; // changed from right shift
|
|
if (mix) crc ^= 0x31;// changed from 0x8C;
|
|
inbyte <<= 1; // changed from right shift
|
|
}
|
|
}
|
|
return crc;
|
|
}
|
|
#endif // PLUGIN_100
|