initial
This commit is contained in:
commit
0c3af5d9c7
|
@ -0,0 +1,228 @@
|
|||
#define BUILDNR 0x07 // shown in version
|
||||
#define REVNR 0x33 // shown in version and startup string
|
||||
#define MIN_RAW_PULSES 20 // =8 bits. Minimal number of bits*2 that need to have been received before we spend CPU time on decoding the signal.
|
||||
#define RAWSIGNAL_SAMPLE_RATE 30 // Sample width / resolution in uSec for raw RF pulses.
|
||||
#define MIN_PULSE_LENGTH 25 // Pulses shorter than this value in uSec. will be seen as garbage and not taken as actual pulses.
|
||||
#define SIGNAL_TIMEOUT 7 // Timeout, after this time in mSec. the RF signal will be considered to have stopped.
|
||||
#define SIGNAL_REPEAT_TIME 500 // Time in mSec. in which the same RF signal should not be accepted again. Filters out retransmits.
|
||||
#define BAUD 57600 // Baudrate for serial communication.
|
||||
#define TRANSMITTER_STABLE_DELAY 500 // delay to let the transmitter become stable (Note: Aurel RTX MID needs 500µS/0,5ms).
|
||||
#define RAW_BUFFER_SIZE 512 // Maximum number of pulses that is received in one go.
|
||||
#define PLUGIN_MAX 55 // Maximum number of Receive plugins
|
||||
#define PLUGIN_TX_MAX 26 // Maximum number of Transmit plugins
|
||||
#define SCAN_HIGH_TIME 50 // tijdsinterval in ms. voor achtergrondtaken snelle verwerking
|
||||
#define FOCUS_TIME 50 // Duration in mSec. that, after receiving serial data from USB only the serial port is checked.
|
||||
#define INPUT_COMMAND_SIZE 60 // Maximum number of characters that a command via serial can be.
|
||||
#define PRINT_BUFFER_SIZE 60 // Maximum number of characters that a command should print in one go via the print buffer.
|
||||
|
||||
// to include Config_xx.c files:
|
||||
#define stringify(x) #x
|
||||
#define CONFIGFILE2(a, b) stringify(a/Config/b)
|
||||
#define CONFIGFILE(a, b) CONFIGFILE2(a, b)
|
||||
#define CONFIG_FILE Config_01.c
|
||||
#include CONFIGFILE(SKETCH_PATH,CONFIG_FILE)
|
||||
|
||||
#define VALUE_PAIR 44
|
||||
#define VALUE_ALLOFF 55
|
||||
#define VALUE_OFF 74
|
||||
#define VALUE_ON 75
|
||||
#define VALUE_DIM 76
|
||||
#define VALUE_BRIGHT 77
|
||||
#define VALUE_UP 78
|
||||
#define VALUE_DOWN 79
|
||||
#define VALUE_STOP 80
|
||||
#define VALUE_CONFIRM 81
|
||||
#define VALUE_LIMIT 82
|
||||
#define VALUE_ALLON 141
|
||||
|
||||
// PIN Definition
|
||||
#define PIN_BSF_0 22 // Board Specific Function lijn-0
|
||||
#define PIN_BSF_1 23 // Board Specific Function lijn-1
|
||||
#define PIN_BSF_2 24 // Board Specific Function lijn-2
|
||||
#define PIN_BSF_3 25 // Board Specific Function lijn-3
|
||||
#define PIN_RF_TX_VCC 15 // +5 volt / Vcc power to the transmitter on this pin
|
||||
#define PIN_RF_TX_DATA 14 // Data to the 433Mhz transmitter on this pin
|
||||
#define PIN_RF_RX_VCC 16 // Power to the receiver on this pin
|
||||
#define PIN_RF_RX_DATA 19 // On this input, the 433Mhz-RF signal is received. LOW when no signal.
|
||||
|
||||
//****************************************************************************************************************************************
|
||||
byte dummy=1; // get the linker going. Bug in Arduino. (old versions?)
|
||||
|
||||
void(*Reboot)(void)=0; // reset function on adres 0.
|
||||
byte PKSequenceNumber=0; // 1 byte packet counter
|
||||
boolean RFDebug=false; // debug RF signals with plugin 001
|
||||
boolean RFUDebug=false; // debug RF signals with plugin 254
|
||||
boolean QRFDebug=false; // debug RF signals with plugin 254 but no multiplication
|
||||
|
||||
uint8_t RFbit,RFport; // for processing RF signals.
|
||||
|
||||
char pbuffer[PRINT_BUFFER_SIZE]; // Buffer for printing data
|
||||
char InputBuffer_Serial[INPUT_COMMAND_SIZE]; // Buffer for Seriel data
|
||||
|
||||
// Van alle devices die worden mee gecompileerd, worden in een tabel de adressen opgeslagen zodat hier naar toe gesprongen kan worden
|
||||
void PluginInit(void);
|
||||
void PluginTXInit(void);
|
||||
boolean (*Plugin_ptr[PLUGIN_MAX])(byte, char*); // Receive plugins
|
||||
byte Plugin_id[PLUGIN_MAX];
|
||||
boolean (*PluginTX_ptr[PLUGIN_TX_MAX])(byte, char*); // Transmit plugins
|
||||
byte PluginTX_id[PLUGIN_TX_MAX];
|
||||
|
||||
void PrintHex8(uint8_t *data, uint8_t length); // prototype
|
||||
void PrintHexByte(uint8_t data); // prototype
|
||||
byte reverseBits(byte data); // prototype
|
||||
void RFLinkHW( void ); // prototype
|
||||
|
||||
struct RawSignalStruct // Raw signal variabelen places in a struct
|
||||
{
|
||||
int Number; // Number of pulses, times two as every pulse has a mark and a space.
|
||||
byte Repeats; // Number of re-transmits on transmit actions.
|
||||
byte Delay; // Delay in ms. after transmit of a single RF pulse packet
|
||||
byte Multiply; // Pulses[] * Multiply is the real pulse time in microseconds
|
||||
unsigned long Time; // Timestamp indicating when the signal was received (millis())
|
||||
byte Pulses[RAW_BUFFER_SIZE+2]; // Table with the measured pulses in microseconds divided by RawSignal.Multiply. (halves RAM usage)
|
||||
// First pulse is located in element 1. Element 0 is used for special purposes, like signalling the use of a specific plugin
|
||||
} RawSignal={0,0,0,0,0,0L};
|
||||
// ===============================================================================
|
||||
unsigned long RepeatingTimer=0L;
|
||||
unsigned long SignalCRC=0L; // holds the bitstream value for some plugins to identify RF repeats
|
||||
unsigned long SignalHash=0L; // holds the processed plugin number
|
||||
unsigned long SignalHashPrevious=0L; // holds the last processed plugin number
|
||||
|
||||
void setup() {
|
||||
Serial.begin(BAUD); // Initialise the serial port
|
||||
pinMode(PIN_RF_RX_DATA, INPUT); // Initialise in/output ports
|
||||
pinMode(PIN_RF_TX_DATA, OUTPUT); // Initialise in/output ports
|
||||
pinMode(PIN_RF_TX_VCC, OUTPUT); // Initialise in/output ports
|
||||
pinMode(PIN_RF_RX_VCC, OUTPUT); // Initialise in/output ports
|
||||
digitalWrite(PIN_RF_RX_VCC,HIGH); // turn VCC to RF receiver ON
|
||||
digitalWrite(PIN_RF_RX_DATA,INPUT_PULLUP); // pull-up resister on (to prevent garbage)
|
||||
|
||||
pinMode(PIN_BSF_0,OUTPUT); // rflink board switch signal
|
||||
digitalWrite(PIN_BSF_0,HIGH); // rflink board switch signal
|
||||
|
||||
RFbit=digitalPinToBitMask(PIN_RF_RX_DATA);
|
||||
RFport=digitalPinToPort(PIN_RF_RX_DATA);
|
||||
Serial.print(F("20;00;Nodo RadioFrequencyLink - RFLink Gateway V1.1 - "));
|
||||
sprintf(InputBuffer_Serial,"R%02x;",REVNR);
|
||||
Serial.println(InputBuffer_Serial);
|
||||
|
||||
PKSequenceNumber++;
|
||||
PluginInit();
|
||||
PluginTXInit();
|
||||
}
|
||||
|
||||
void loop() {
|
||||
byte SerialInByte=0; // incoming character value
|
||||
int SerialInByteCounter=0; // number of bytes counter
|
||||
|
||||
byte ValidCommand=0;
|
||||
unsigned long FocusTimer=0L; // Timer to keep focus on the task during communication
|
||||
InputBuffer_Serial[0]=0; // erase serial buffer string
|
||||
|
||||
while(true) {
|
||||
ScanEvent(); // Scan for RF events
|
||||
// SERIAL: *************** kijk of er data klaar staat op de seriele poort **********************
|
||||
if(Serial.available()) {
|
||||
FocusTimer=millis()+FOCUS_TIME;
|
||||
|
||||
while(FocusTimer>millis()) { // standby
|
||||
if(Serial.available()) {
|
||||
SerialInByte=Serial.read();
|
||||
|
||||
if(isprint(SerialInByte))
|
||||
if(SerialInByteCounter<(INPUT_COMMAND_SIZE-1))
|
||||
InputBuffer_Serial[SerialInByteCounter++]=SerialInByte;
|
||||
|
||||
if(SerialInByte=='\n') { // new line character
|
||||
InputBuffer_Serial[SerialInByteCounter]=0; // serieel data is complete
|
||||
//Serial.print("20;incoming;");
|
||||
//Serial.println(InputBuffer_Serial);
|
||||
if (strlen(InputBuffer_Serial) > 7){ // need to see minimal 8 characters on the serial port
|
||||
// 10;....;..;ON;
|
||||
if (strncmp (InputBuffer_Serial,"10;",3) == 0) { // Command from Master to RFLink
|
||||
// -------------------------------------------------------
|
||||
// Handle Device Management Commands
|
||||
// -------------------------------------------------------
|
||||
if (strcasecmp(InputBuffer_Serial+3,"PING;")==0) {
|
||||
sprintf(InputBuffer_Serial,"20;%02X;PONG;",PKSequenceNumber++);
|
||||
Serial.println(InputBuffer_Serial);
|
||||
} else
|
||||
if (strcasecmp(InputBuffer_Serial+3,"REBOOT;")==0) {
|
||||
strcpy(InputBuffer_Serial,"reboot");
|
||||
Reboot();
|
||||
} else
|
||||
if (strncasecmp(InputBuffer_Serial+3,"RFDEBUG=O",9) == 0) {
|
||||
if (InputBuffer_Serial[12] == 'N' || InputBuffer_Serial[12] == 'n' ) {
|
||||
RFDebug=true; // full debug on
|
||||
RFUDebug=false; // undecoded debug off
|
||||
QRFDebug=false; // undecoded debug off
|
||||
sprintf(InputBuffer_Serial,"20;%02X;RFDEBUG=ON;",PKSequenceNumber++);
|
||||
} else {
|
||||
RFDebug=false; // full debug off
|
||||
sprintf(InputBuffer_Serial,"20;%02X;RFDEBUG=OFF;",PKSequenceNumber++);
|
||||
}
|
||||
Serial.println(InputBuffer_Serial);
|
||||
} else
|
||||
if (strncasecmp(InputBuffer_Serial+3,"RFUDEBUG=O",10) == 0) {
|
||||
if (InputBuffer_Serial[13] == 'N' || InputBuffer_Serial[13] == 'n') {
|
||||
RFUDebug=true; // undecoded debug on
|
||||
QRFDebug=false; // undecoded debug off
|
||||
RFDebug=false; // full debug off
|
||||
sprintf(InputBuffer_Serial,"20;%02X;RFUDEBUG=ON;",PKSequenceNumber++);
|
||||
} else {
|
||||
RFUDebug=false; // undecoded debug off
|
||||
sprintf(InputBuffer_Serial,"20;%02X;RFUDEBUG=OFF;",PKSequenceNumber++);
|
||||
}
|
||||
Serial.println(InputBuffer_Serial);
|
||||
} else
|
||||
if (strncasecmp(InputBuffer_Serial+3,"QRFDEBUG=O",10) == 0) {
|
||||
if (InputBuffer_Serial[13] == 'N' || InputBuffer_Serial[13] == 'n') {
|
||||
QRFDebug=true; // undecoded debug on
|
||||
RFUDebug=false; // undecoded debug off
|
||||
RFDebug=false; // full debug off
|
||||
sprintf(InputBuffer_Serial,"20;%02X;QRFDEBUG=ON;",PKSequenceNumber++);
|
||||
} else {
|
||||
QRFDebug=false; // undecoded debug off
|
||||
sprintf(InputBuffer_Serial,"20;%02X;QRFDEBUG=OFF;",PKSequenceNumber++);
|
||||
}
|
||||
Serial.println(InputBuffer_Serial);
|
||||
} else
|
||||
if (strncasecmp(InputBuffer_Serial+3,"VERSION",7) == 0) {
|
||||
sprintf(InputBuffer_Serial,"20;%02X;VER=1.1;REV=%02x;BUILD=%02x;",PKSequenceNumber++,REVNR, BUILDNR);
|
||||
Serial.println(InputBuffer_Serial);
|
||||
} else {
|
||||
// -------------------------------------------------------
|
||||
// Handle Generic Commands / Translate protocol data into Nodo text commands
|
||||
// -------------------------------------------------------
|
||||
// check plugins
|
||||
if (InputBuffer_Serial[SerialInByteCounter-1]==';') InputBuffer_Serial[SerialInByteCounter-1]=0; // remove last ";" char
|
||||
if(PluginTXCall(0, InputBuffer_Serial)) {
|
||||
ValidCommand=1;
|
||||
} else {
|
||||
// Answer that an invalid command was received?
|
||||
ValidCommand=2;
|
||||
}
|
||||
}
|
||||
}
|
||||
} // if > 7
|
||||
if (ValidCommand != 0) {
|
||||
if (ValidCommand==1) {
|
||||
sprintf(InputBuffer_Serial,"20;%02X;OK;",PKSequenceNumber++);
|
||||
Serial.println( InputBuffer_Serial );
|
||||
} else {
|
||||
sprintf(InputBuffer_Serial, "20;%02X;CMD UNKNOWN;", PKSequenceNumber++); // Node and packet number
|
||||
Serial.println( InputBuffer_Serial );
|
||||
}
|
||||
}
|
||||
SerialInByteCounter=0;
|
||||
InputBuffer_Serial[0]=0; // serial data has been processed.
|
||||
ValidCommand=0;
|
||||
FocusTimer=millis()+FOCUS_TIME;
|
||||
}// if(SerialInByte
|
||||
}// if(Serial.available())
|
||||
}// while
|
||||
}// if(Serial.available())
|
||||
}// while
|
||||
} // void
|
||||
/*********************************************************************************************/
|
||||
|
|
@ -0,0 +1,112 @@
|
|||
// ****************************************************************************************************************************************
|
||||
// RFLink List of Plugins
|
||||
// ****************************************************************************************************************************************
|
||||
// Here are all plugins listed that are supported and used after compilation.
|
||||
// When needed additional plugins can be added or selected plugins can be enabled/disabled.
|
||||
//
|
||||
// BEWARE OF THE PLUGIN_MAX setting!! TX: 51 RX: 24
|
||||
// ****************************************************************************************************************************************
|
||||
// Translation Plugin for oversized packets due to their breaks/pause being too short between packets
|
||||
// Used for Flamingo FA500R and various others, do NOT exclude this plugin.
|
||||
#define PLUGIN_001 // DO NOT CHANGE OR EXCLUDE!!
|
||||
// ------------------------------------------------------------------------
|
||||
// -- Any of the following protocols can be excluded whenever not needed --
|
||||
// ------------------------------------------------------------------------
|
||||
#define PLUGIN_002 // Lacrosse v2 2300/3600
|
||||
#define PLUGIN_003 // Kaku : Klik-Aan-Klik-Uit (with code wheel) aka ARC
|
||||
#define PLUGIN_004 // NewKAKU : Klik-Aan-Klik-Uit with automatic coding aka Intertechno.
|
||||
#define PLUGIN_005 // Eurodomest
|
||||
#define PLUGIN_006 // Blyss
|
||||
#define PLUGIN_007 // Conrad RSL2
|
||||
#define PLUGIN_008 // Kambrook
|
||||
#define PLUGIN_009 // X10 RF
|
||||
#define PLUGIN_010 // TRC02 RGB Switch
|
||||
#define PLUGIN_011 // Home Confort
|
||||
#define PLUGIN_012 // Flamingo FA500R
|
||||
#define PLUGIN_013 // Powerfix/Quigg
|
||||
#define PLUGIN_014 // Ikea Koppla
|
||||
#define PLUGIN_015 // Home Easy EU
|
||||
// -------------------
|
||||
// Weather sensors
|
||||
// -------------------
|
||||
#define PLUGIN_030 // Alecto V1 (WS3500) 434 MHz.
|
||||
#define PLUGIN_031 // Alecto V3 (WS1100/WS1200/WSD-19) 433.9 MHz.
|
||||
#define PLUGIN_032 // Alecto V4
|
||||
#define PLUGIN_033 // Conrad Pool Thermometer
|
||||
#define PLUGIN_034 // Cresta
|
||||
#define PLUGIN_035 // Imagintronix
|
||||
#define PLUGIN_040 // Mebus
|
||||
#define PLUGIN_041 // LaCrosse v3 ws7000
|
||||
#define PLUGIN_042 // UPM/Esic
|
||||
#define PLUGIN_043 // LaCrosse v1
|
||||
#define PLUGIN_044 // Auriol v3
|
||||
#define PLUGIN_045 // Auriol
|
||||
#define PLUGIN_046 // Auriol v2 / Xiron
|
||||
#define PLUGIN_048 // Oregon V1/2/3
|
||||
// -------------------
|
||||
// Motion Sensors, include when needed
|
||||
// -------------------
|
||||
#define PLUGIN_060 // Ajax Chubb Varel 433 MHz. motion sensors
|
||||
#define PLUGIN_061 // Chinese PIR motion door and window sensors
|
||||
#define PLUGIN_062 // Chuango Alarm Devices
|
||||
#define PLUGIN_063 // Oregon PIR/ALARM/LIGHT
|
||||
// -------------------
|
||||
// Doorbells
|
||||
// -------------------
|
||||
#define PLUGIN_070 // Select Plus (Action - Quhwa)
|
||||
#define PLUGIN_071 // Plieger York
|
||||
#define PLUGIN_072 // Byron SX doorbell
|
||||
#define PLUGIN_073 // Deltronic doorbell
|
||||
#define PLUGIN_074 // RL02
|
||||
#define PLUGIN_075 // Silvercrest
|
||||
// -------------------
|
||||
// Smoke detectors / Fire Places
|
||||
// -------------------
|
||||
#define PLUGIN_080 // Flamingo FA20 / KD101 smoke detector
|
||||
#define PLUGIN_082 // Mertik Maxitrol / Dru fireplace
|
||||
//#define PLUGIN_083 // Alecto SA33
|
||||
// -------------------
|
||||
// 868 MHZ
|
||||
// -------------------
|
||||
#define PLUGIN_100 // Alecto V2 (DKW2012/ACH2010) 868 MHz. => PLANNED
|
||||
// -------------------
|
||||
// Housekeeping
|
||||
// -------------------
|
||||
#define PLUGIN_090 // Nodo Slave conversion plugin
|
||||
#define PLUGIN_254 // Debug to show unsupported packets
|
||||
// ****************************************************************************************************************************************
|
||||
// RFLink List of Plugins that have TRANSMIT functionality
|
||||
// ****************************************************************************************************************************************
|
||||
// Here are all plugins listed that are supported and used after compilation.
|
||||
// When needed additional plugins can be added or selected plugins can be enabled/disabled.
|
||||
// ****************************************************************************************************************************************
|
||||
// ------------------------------------------------------------------------
|
||||
// -- Any of the following protocols can be excluded whenever not needed --
|
||||
// ------------------------------------------------------------------------
|
||||
#define PLUGIN_TX_003 // Kaku : Klik-Aan-Klik-Uit (with code wheel) aka ARC
|
||||
#define PLUGIN_TX_004 // NewKAKU : Klik-Aan-Klik-Uit with automatic coding aka Intertechno.
|
||||
#define PLUGIN_TX_005 // Eurodomest
|
||||
#define PLUGIN_TX_006 // Blyss
|
||||
#define PLUGIN_TX_007 // Conrad RSL2
|
||||
#define PLUGIN_TX_008 // Kambrook
|
||||
#define PLUGIN_TX_009 // X10 RF
|
||||
#define PLUGIN_TX_010 // TRC02 RGB switch
|
||||
#define PLUGIN_TX_011 // Home Confort
|
||||
#define PLUGIN_TX_012 // Flamingo FA500R (11)
|
||||
#define PLUGIN_TX_013 // Powerfix/Quigg
|
||||
#define PLUGIN_TX_015 // Home Easy EU (14)
|
||||
// -------------------
|
||||
// Doorbells
|
||||
// -------------------
|
||||
#define PLUGIN_TX_070 // Select Plus (Action - Quhwa)
|
||||
#define PLUGIN_TX_072 // Byron SX doorbell
|
||||
#define PLUGIN_TX_073 // Deltronic doorbell
|
||||
#define PLUGIN_TX_074 // RL02
|
||||
// -------------------
|
||||
// Smoke detectors
|
||||
// -------------------
|
||||
#define PLUGIN_TX_080 // Flamingo FA20 / KD101 smoke detector
|
||||
#define PLUGIN_TX_082 // Mertik Maxitrol / Dru fireplace
|
||||
// -------------------
|
||||
// -=#=-
|
||||
// -------------------
|
|
@ -0,0 +1,161 @@
|
|||
RFLink Gateway Commands and Data fields
|
||||
|
||||
The use of this protocol is free for both server and client sides of the implementation
|
||||
Data is send serial (via USB) as "text" at a speed of 57600 baud (N,8,1)
|
||||
It is sufficient to open a port and listen to the data.
|
||||
Each text line contains information that has been received via RF signals.
|
||||
|
||||
|
||||
Packet structure - Received data from RF:
|
||||
-----------------------------------------
|
||||
20;ID=9999;Name;LABEL=data;
|
||||
|
||||
20 => Node number 20 means from the RFLink Gateway to the master, 10 means from the master to the RFLink Gateway
|
||||
; => field separator
|
||||
NAME => Device name (can be used to display in applications etc.)
|
||||
LABEL=data => contains the field type and data for that field, can be present multiple times per device
|
||||
|
||||
|
||||
Data Fields: (LABEL=data)
|
||||
------------
|
||||
ID=9999 => device ID (often a rolling code and/or device channel number)
|
||||
SWITCH=A16 => House/Unit code like A1, P2, B16 or a button number etc.
|
||||
CMD=ON => Command (ON/OFF/ALLON/ALLOFF)
|
||||
SET_LEVEL=15 => Direct dimming level setting value
|
||||
TEMP=9999 => Temperature (hexadecimal), high bit contains negative sign, needs devision by 10
|
||||
HUM=99 => Humidity (hexadecimal)
|
||||
BARO=9999 => Barometric pressure (hexadecimal)
|
||||
HSTATUS=99 => 0=Normal, 1=Comfortable, 2=Dry, 3=Wet
|
||||
BFORECAST=99 => 0=No Info/Unknown, 1=Sunny, 2=Partly Cloudy, 3=Cloudy, 4=Rain
|
||||
UV=9999 => UV intensity (hexadecimal)
|
||||
LUX=9999 => Light intensity (hexadecimal)
|
||||
BAT=OK => Battery status indicator (OK/LOW)
|
||||
RAIN=1234 => rain rate in mm. (hexadecimal)
|
||||
RAINTOT=1234 => total rain in mm. (hexadecimal)
|
||||
WINSP=9999 => Wind speed in km. p/h (hexadecimal) needs devision by 10
|
||||
AWINSP=9999 => Average Wind speed in km. p/h (hexadecimal) needs devision by 10
|
||||
WINGS=9999 => Wind Gust in km. p/h (hexadecimal)
|
||||
WINDIR=123 => Wind direction 0-15 reflecting 0-360 degrees in 22.5 degree steps (decimal)
|
||||
WINCHL => wind chill (hexadecimal)
|
||||
WINTMP=1234 => Wind meter temperature reading (hexadecimal)
|
||||
CHIME=123 => Chime/Doorbell melody number
|
||||
SMOKEALERT=ON => ON/OFF
|
||||
PIR=ON => ON/OFF
|
||||
CO2=1234 => CO2 air quality
|
||||
SOUND=1234 => Noise level
|
||||
KWATT=1234 => KWatt
|
||||
WATT=1234 => Watt
|
||||
DIST=1234 => Distance
|
||||
METER=1234 => Water flow meter
|
||||
VOLT=1234 => Voltage
|
||||
CURRENT=1234 => Current
|
||||
|
||||
|
||||
Sample data of received RF packets:
|
||||
-----------------------------------
|
||||
20;2D;UPM/Esic;ID=0001;TEMP=00cf;HUM=16;BAT=OK;
|
||||
20;6A;UPM/Esic;ID=1002;WINSP=0041;WINDIR=5A;BAT=OK;
|
||||
20;08;UPM/Esic;ID=1003;RAIN=0010;BAT=OK;
|
||||
20;31;Mebus;ID=c201;TEMP=00cf;
|
||||
20;32;Auriol;ID=008f;TEMP=00d3;BAT=OK;
|
||||
20;A2;Auriol V2;ID=008f;TEMP=00a3;BAT=LOW;
|
||||
20;33;Cresta;ID=3001;TEMP=00b0;HUM=50;
|
||||
20;0C;Cresta;ID=8001;RAIN=001c;
|
||||
20;47;Cresta;ID=8001;WINDIR=0002;WINSP=0060;WINGS=0088;WINCHL=b0;
|
||||
20;47;Cresta;ID=8001;TEMP=00b0;UV=00d0;
|
||||
20;36;Alecto V1;ID=ec02;TEMP=00d1;HUM=14;
|
||||
20;07;Mebus;ID=ea01;TEMP=0017;
|
||||
20;3D;Alecto V1;ID=2000;TEMP=0011;HUM=61;
|
||||
20;26;Alecto V1;ID=0086;RAIN=02ac;
|
||||
20;30;Alecto V1;ID=0020;WINSP=0068;
|
||||
20;16;Alecto V1;ID=0020;WINSP=0020;
|
||||
20;17;Alecto V1;ID=0020;WINDIR=0002;WINGS=0088;
|
||||
20;36;Alecto V1;ID=0020;WINDIR=0002;WINGS=0040;
|
||||
20;74;Oregon TempHygro;ID=0ACC;TEMP=00be;HUM=40;BAT=OK;
|
||||
20;b3;Oregon TempHygro;ID=1a2d;TEMP=00dd;HUM=43;BAT=OK;
|
||||
20;e5;Oregon BTHR;ID=5a6d;TEMP=00be;HUM=40;BARO=03d7;BAT=OK;
|
||||
20;46;Oregon Rain;ID=2a1d;RAIN=0012;RAINTOT=0012;BAT=OK;
|
||||
20;83;Oregon Rain2;ID=2a19;RAIN=002a;RAINTOT=0054;BAT=OK;
|
||||
20;32;Oregon Wind;ID=1a89;WDIR=0045;WINSP=0068;AWINSP=0050;BAT=OK;
|
||||
20;4a;Oregon Wind2;ID=3a0d;WDIR=0021;WINSP=0040;AWINSP=005a;BAT=OK;
|
||||
20;ba;Oregon UVN128/138;ID=ea7c;UV=0030;BAT=OK;
|
||||
20;AF;SelectPlus;ID=1bb4;CHIME=01;
|
||||
20;FC;Plieger York;ID=dd01;CHIME=02;
|
||||
20;47;Byron SX;ID=a66a;CHIME=A9;
|
||||
20;12;Pir;ID=aa66;PIR=ON;
|
||||
20;63;SmokeAlert;ID=123456;SMOKEALERT=ON;
|
||||
20;06;Kaku;ID=41;SWITCH=1;CMD=ON;
|
||||
20;0C;Kaku;ID=41;SWITCH=2;CMD=OFF;
|
||||
20;0D;Kaku;ID=41;SWITCH=2;CMD=ON;
|
||||
20;46;Kaku;ID=44;SWITCH=4;CMD=OFF;
|
||||
20;E0;NewKaku;ID=cac142;SWITCH=1;CMD=ALLOFF;
|
||||
20;3B;NewKaku;ID=cac142;SWITCH=3;CMD=OFF;
|
||||
20;0B;NewKaku;ID=000005;SWITCH=2;CMD=ON;
|
||||
20;0E;NewKaku;ID=000005;SWITCH=2;CMD=OFF;
|
||||
20;12;NewKaku;ID=000002;SWITCH=2;CMD=OFF;
|
||||
20;1E;NewKaku;ID=00000a;SWITCH=2;CMD=OFF;
|
||||
20;1F;NewKaku;ID=00000a;SWITCH=2;CMD=ON;
|
||||
20;01;NewKaku;ID=000007;SWITCH=2;CMD=OFF;
|
||||
20;04;NewKaku;ID=000007;SWITCH=2;CMD=ON;
|
||||
20;04;NewKaku;ID=000007;SWITCH=2;CMD=SET_LEVEL=14;
|
||||
20;0C;HomeEasy;ID=7900b200;SWITCH=0b;CMD=ALLON;
|
||||
20;AD;FA500;ID=0d00b900;SWITCH=0001;CMD=UNKOWN;
|
||||
20;AE;FA500;ID=0a01;SWITCH=0a01;CMD=OFF;
|
||||
20;03;Eurodomest;ID=03696b;SWITCH=00;CMD=OFF;
|
||||
20;04;Eurodomest;ID=03696b;SWITCH=07;CMD=ALLOFF;
|
||||
20;41;Conrad RSL2;ID=010002;SWITCH=03;CMD=ON;
|
||||
20;47;Blyss;ID=ff98;SWITCH=A1;CMD=ON;
|
||||
20;73;Kambrook;ID=010203;SWITCH=A1;CMD=OFF;
|
||||
|
||||
Note that for sensors that only report values like temperature, only the data and the ID are required.
|
||||
Name labels can be thrown away or used for cosmetic purposes.
|
||||
|
||||
For switches, the protocol name has to be stored and re-used on the transmission side.
|
||||
Thus, when a remote control is used to control a device data like below will be send from the RFLink Gateway over USB:
|
||||
20;3B;NewKaku;ID=cac142;SWITCH=3;CMD=OFF;
|
||||
When the state of this switch needs to be changed the following command has to be send:
|
||||
10;NewKaku;0cac142;3;ON;
|
||||
The name label (here "NewKaku") is used to tell the RFLink Gateway what protocol it has to use for the RF broadcast.
|
||||
|
||||
|
||||
|
||||
Special Control Commands - Send:
|
||||
--------------------------------
|
||||
10;REBOOT; => Reboot RFLink Gateway hardware
|
||||
10;PING; => a "keep alive" function. Is replied with: 20;99;PONG;
|
||||
10;VERSION; => Version and build indicator. Is replied with: 20;99;"RFLink Gateway software version";
|
||||
10;RFDEBUG=ON; => ON/OFF to Enable/Disable showing of RF packets. Is replied with: 20;99;RFDEBUG="state";
|
||||
10;RFUDEBUG=ON; => ON/OFF to Enable/Disable showing of undecoded RF packets. Is replied with: 20;99;RFUDEBUG="state";
|
||||
10;QRFDEBUG=ON; => ON/OFF to Enable/Disable showing of undecoded RF packets. Is replied with: 20;99;QRFDEBUG="state";
|
||||
QRFDEBUG is a faster version of RFUDEBUG but all pulse times are shown in hexadecimal and need to be multiplied by 30
|
||||
|
||||
|
||||
Packet structure - To Send data via RF:
|
||||
---------------------------------------
|
||||
10;Protocol Name;device address,button number;action;
|
||||
|
||||
Sample data of transmitted RF packets:
|
||||
--------------------------------------
|
||||
10;Kaku;00004d;1;OFF; => Kaku/ARC protocol;address;action (ON/OFF)
|
||||
10;AB400D;00004d;1;OFF; => Sartano protocol;address;action (ON/OFF)
|
||||
10;Impuls;00004d;1;OFF; => Impuls protocol;address;action (ON/OFF)
|
||||
10;NewKaku;00c142;1;ON; => Newkaku/AC protocol;address (24 bits);button number (hexadecimal 0x0-0x0f);action (ON/OFF/ALLON/ALLOFF/15 - 1 to 15 for direct dim level)
|
||||
10;NewKaku;128ac4d;1;OFF; => Newkaku/AC protocol;address (28 bits);button number (hexadecimal 0x0-0x0f);action (ON/OFF/ALLON/ALLOFF/15 - 1 to 15 for direct dim level)
|
||||
10;Eurodomest;123456;01;ON; => Eurodomest protocol;address;button number;action (ON/OFF/ALLON/ALLOFF)
|
||||
10;Blyss;ff98;A1;OFF; => Blyss protocol;address;button;action (ON/OFF/ALLON/ALLOFF)
|
||||
10;Conrad;ff0607;1;OFF; => Conrad RSL protocol, address, button number, action (ON/OFF/ALLON/ALLOFF)
|
||||
10;Kambrook;050325;a1;ON; => Kambrook protocol, address, unit/button number, action (ON/OFF)
|
||||
10;X10;000041;1;OFF; => X10 protocol;address;action (ON/OFF)
|
||||
10;HomeConfort;01b523;D3;ON;=> HomeConfort protocol;address;action (ON/OFF)
|
||||
10;FA500;001b523;D3;ON; => Flamingo protocol;address;action (ON/OFF)
|
||||
10;Powerfix;000080;0;ON; => Powerfix/Quigg/Chacon protocol;address;action (ON/OFF)
|
||||
10;Ikea Koppla;000080;0;ON; => Koppla protocol;address;action (ON/OFF)
|
||||
10;HomeEasy;7900b100;3;ON; => Home Easy protocol;address;action (ON/OFF/ALLON/ALLOFF)
|
||||
10;EV1527;000080;0;ON; => EV1527 protocol;address;device 0x00-0x0f,action ON/OFF
|
||||
10;Chuango;000080;2;ON; => Chuango Protocol;address;action (ON/OFF/ALLON/ALLOFF)
|
||||
10;Selectplus;001c33; => SelectPlus protocol;address
|
||||
10;Byron;112233;01;OFF; => Dyron SX protocol;address;ringtone
|
||||
10;DELTRONIC;001c33; => Deltronic protocol;address
|
||||
10;BYRON;00009F;01;ON; => Byron protocol;address;chime number,command
|
||||
10;FA20RF;67f570;1;ON; => Flamingo FA20RF / FA21 / KD101 protocol, address, button number, action (ON/OFF/ALLON/ALLOFF)
|
||||
10;MERTIK;64;UP; => Mertik protocol, address, command
|
Binary file not shown.
After Width: | Height: | Size: 40 KiB |
|
@ -0,0 +1,23 @@
|
|||
RFLink Loader Version 1.02
|
||||
|
||||
|
||||
The RFLink Loader program runs on Windows and can program an Arduino Mega 2560 board
|
||||
with the RFLink software.
|
||||
You do not need any Arduino IDE/Compiler etc.
|
||||
|
||||
|
||||
Steps:
|
||||
------
|
||||
- Launch the program
|
||||
- Select the file you want to program (rflink.cpp.hex)
|
||||
- Select the serial port to which the Arduino is connected.
|
||||
- Hit the "program" button and wait for the process to finish.
|
||||
|
||||
|
||||
|
||||
History:
|
||||
--------
|
||||
1.02 Fixed: could not use serial ports > 9
|
||||
1.01 Fixed: could not load the hex file if the path name contained a space
|
||||
Added: test serial port availability before trying to program the Arduino
|
||||
1.00 Initial Release
|
|
@ -0,0 +1,273 @@
|
|||
! ============================================================================
|
||||
! Only for educational purposes, the source might not be synchronized with the
|
||||
! latest release!
|
||||
! For normal operation, use the RFLink Loader that includes the latest release
|
||||
! ============================================================================
|
||||
|
||||
Please note that the RFLink Gateway is a freeware project.
|
||||
Stuntteam is not making money in any way.
|
||||
This means that there are no unlimited funds to purchase test devices,
|
||||
it also means the project has to rely on you, the user, to send debug data.
|
||||
|
||||
If you want to contribute to this project, you can send a donation which is more than welcome (see www.nemcon.nl/blog2 donation button),
|
||||
or help with sending debug data of unsupported devices (you can even write and contribute plugins and/or code fixes),
|
||||
or donate the device that you would like to see supported.
|
||||
|
||||
Right now we are looking for some older remotes and/or switches.
|
||||
Like for example: Impuls, Ikea Koppla, Powerfix, Blyss, Home Confort, Conrad, Kambrook, Everflourish
|
||||
For the implementation of the planned 2.4Ghz support we could use some simple MySensor devices.
|
||||
For the implementation of the planned 868Mhz support we could use some devices as well.
|
||||
If you have anything that you do not use, send a mail to frankzirrone@gmail.com
|
||||
Thanks in advance!
|
||||
|
||||
------------------------
|
||||
Synology NAS:
|
||||
If you want to use RFLink with a Synology NAS you can use:
|
||||
- an Arduino Mega clone based on CH340 USB/serial chip
|
||||
In all other cases:
|
||||
- connect a 10 uF capacitor between reset and ground on the Arduino.
|
||||
Simply stick the pins of the capacitor in the power connector socket.
|
||||
When you want to update the firmware of the Arduino, remove the capacitor and reconnect it when done.
|
||||
For details about the Domoticz Synology package check out: http://www.jadahl.com
|
||||
------------------------
|
||||
RFlink via Network Connection:
|
||||
It is possible to use RFlink via a network connection using ser2net.
|
||||
------------------------
|
||||
You can now use the RFLink Gateway with the following home automation software:
|
||||
Domoticz
|
||||
Jeedom
|
||||
------------------------
|
||||
R35: (Work-In-Progress) Build 05
|
||||
- Added: Brel motor support
|
||||
- Fixed: Oregon OWL CM119, CM160, CM180
|
||||
- Fixed: Corrected WH440 temperature values
|
||||
- Fixed: Improved Philips SBC
|
||||
- Fixed: Improved Chacon EMW200
|
||||
- Fixed: Removed a slash in the UPM/Esic name
|
||||
- Tested: tested and working: Lidl / Libra TR502MSV switches
|
||||
|
||||
R34:
|
||||
- Added: Heidemann HX Silverline 70290
|
||||
- Added: Eurochron EAS 301Z / EAS 302
|
||||
- Added: Znane-01 switch set sold at Biedronka (Impuls clone)
|
||||
- Added: HomeEasy HE800 protocol support
|
||||
- Added: Fine Offset Electronics WH2, Agimex Rosenborg 66796, ClimeMET CM9088
|
||||
- Added: Somfy Smoove Origin RTS (433mhz) (receive)
|
||||
- Tested: Eurodomest 972086 (Sold at Action in Belgium)
|
||||
- Added: Eurodomest revised protocol (full autodetection)
|
||||
- Added: Prologue temperature sensor support
|
||||
- Tested: tested and working: Home Confort, Smart Home PRF-100 switch set
|
||||
- Fixed: Auto detection of "Emil Lux"/LUX-Tools remote control/switch set (Sold at Obi.de Art.Nr. 2087971) (Impuls clone)
|
||||
- Fixed: Alecto WS1100 working properly again (Adjusted pulse range and displayed humidity value)
|
||||
- Fixed: Byron SX receive and send commands
|
||||
- Fixed: Ikea Koppla Send routines
|
||||
- Fixed: Improved the Impuls remote detection
|
||||
- Fixed: Impuls transmit
|
||||
- Changed: added checks for valid temperatures in various plugins
|
||||
|
||||
R33:
|
||||
- Updated RFlink loader to version 1.03 to include a serial log option with command sending ability!
|
||||
|
||||
- Added: Full automatic 'Flamingo FA500/SilverCrest 91210/60494 RCS AAA3680/Mumbi M-FS300/Toom 1919384' protocol support! (send & receive!)
|
||||
Note: re-learn your FA500 Remote in Domoticz
|
||||
- Added: Unitec 48111/48112 (receive)
|
||||
- Added: Avidsen
|
||||
- Added: Somfy Telis (433mhz) (receive)
|
||||
- Fixed: Extreme temperature value rejection for various sensor types (TFA/LaCrosse)
|
||||
- Fixed: Improved Blyss send routines
|
||||
- Added: Support for old Xiron temperature sensor in Cresta plugin (Temperature only sensor was not handled)
|
||||
- Added: Biowin meteo sensor
|
||||
- Fixed: Imagintronix humidity and temperature values were sometimes incorrect
|
||||
- Fixed: AB4400/Sartano/Phenix detection corrected
|
||||
- Fixed: Modification to allow EMW200/203 to work better
|
||||
- Changed: ARC (and compatible) remote and switch handling improved
|
||||
- Fixed: Improved Impuls handling
|
||||
- Fixed: Auriol V3 minus temperature handling
|
||||
- Fixed: TRC02RGB send
|
||||
- Fixed: Oregon OWL180 data
|
||||
- Changed: Aster signal detection so that L^Home model 32311T is recognized as well
|
||||
- Changed: ID for Nodo Slave 'Wind direction/Wind gust' combined so that Domoticz can handle the data
|
||||
- Changed: Protocol handling order for 'multi-protocol' transmitting devices
|
||||
|
||||
R32:
|
||||
- Added: Europe RS-200, Conrad TR-200
|
||||
- Added: Bofu motor transmit
|
||||
- Added: ARC group command support
|
||||
- Added: support for ARC based tri-state protocol
|
||||
- Tested and working: Hormann 868mhz receive
|
||||
- Changed: Bofu motor signal repetition detection improved
|
||||
- Fixed: Aster transmit routines
|
||||
- Fixed: plugin 003 output was not processed correctly by Domoticz
|
||||
- Fixed: ARC higher address numbers did not work correctly in combination with Domoticz
|
||||
- Changed: Chacon/Powerfix/Mandolyn/Quigg transmit routine and optimized timing
|
||||
- Changed: Increased the number of re-transmits in the Home Easy protocol to improve signal reception and distance
|
||||
- Changed: Sensor plugins now suppressing ARC derived protocols a bit better
|
||||
|
||||
R31:
|
||||
- New Device: Forrinx Wireless Doorbell
|
||||
- New Device: TRC02 RGB controller
|
||||
- New Device: OWL CM180
|
||||
- New Device: ELMES CTX3H and CTX4H contact sensor
|
||||
- New Device: Bofu Motor (receive)
|
||||
- New Device: Aster / GEMINI EMC/99/STI/037
|
||||
- Changed: EV1527 based sensors were reported as X10, now they are reported as EV1527. Note that it might be needed to re-add the devices to Domoticz
|
||||
- Changed: increased number of retransmits for ARC and AC protocols
|
||||
- Fixed: Koppla switch number was incorrect
|
||||
- Fixed: Powerfix/Mandolyn/Chacon Parity calculation in send routines
|
||||
- Fixed: Powerfix/Mandolyn/Chacon timing
|
||||
- Fixed Windspeed value for WS2300
|
||||
- Fixed: Home Easy HE300 ON/OFF signal was reversed
|
||||
- Changed: HomeEasy suppressing additional protocol data to avoid reporting the same event multiple times under different protocols
|
||||
- Fixed: More fixes to avoid duplicate reporting of the same event (various protocols)
|
||||
|
||||
R30:
|
||||
- New Device: Conrad 9771 Pool Thermometer
|
||||
- New Device: SilverCrest Z31370-TX Doorbell
|
||||
- New Device: Smartwares remote controls (among others: SH5-TDR-K 10.037.17)
|
||||
- New Device: Chuango Alarm devices Motion/Door/Window etc. (among others: CG-105S)
|
||||
- New Device: Oregon Scientific NR868 PIR/night light
|
||||
- New Device: Oregon Scientific MSR939 PIR
|
||||
- New Device: Imagintronix Temperature/Soil humidity sensor
|
||||
- New Device: Ikea Koppla (receive)
|
||||
- New Device: Chacon (TR-502MSV, NR.RC402)
|
||||
- Fixed: Arc protocol send
|
||||
- Fixed: Impuls. Note: pair devices with the KAKU protocol, the remote is recognized separately. (Needs more tests!)
|
||||
- Changed: Plugin 3 send method, combined routines
|
||||
- Changed: HomeConfort was recognized as Impuls, now using GDR2 name
|
||||
- Changed: HomeEasy remotes can deliver various signals, now skipping KAKU compatible signals and just reporting the HomeEasy code when both codes are transmitted
|
||||
- Fixed: HomeEasy group on/off command was reversed for HE8xx devices, now correctly detects differences between HE3xx and HE8xx
|
||||
- Fixed: HomeEasy was not able to control HE87x switches, changed the entire transmit routine
|
||||
- Changed: stretched Xiron timing checks
|
||||
- Changed: Various timing modifications (NewKaku/AC, Blyss) due to the new timing introduced at version R26
|
||||
- Changed: Plugin 61, Chinese Alarm devices, reversed bits as it seemed to correspond better to bit settings, increased address range
|
||||
- Fixed: Flamingo Smokedetector packet detection tightened up to prevent false positives
|
||||
- Fixed: Corrected Conrad RSL command interpretation
|
||||
- Added: Extended Nodo Slave support to support separate and combined sensors
|
||||
- Added: Extended Nodo Slave support to support pulse meters
|
||||
|
||||
R29:
|
||||
- Fixed: AC/NewKaku high unit numbers were incorrect.
|
||||
If you already have devices with high unit numbers in Domoticz, just throw them away and let them be recognized again
|
||||
|
||||
R28:
|
||||
- Fixed: FA20RF smoke detector transmit from Domoticz
|
||||
|
||||
R27:
|
||||
- Added: OSV1 battery status
|
||||
- Fixed: OSV1 boundaries and removed some debug info
|
||||
- Fixed: Some plugins set an incorrect sampling rate divider value
|
||||
- Changed: AlectoV1 false positives filter was too agressive
|
||||
|
||||
R26:
|
||||
- Added: QRFDEBUG command to do faster logging of undecoded data
|
||||
- Added: VERSION command
|
||||
- Added: Powerfix/Quigg switches
|
||||
- Added: proper Lacrosse V3 WS7000 sensor support
|
||||
- Changed: config file and plugin integration
|
||||
- Changed: timeout and divider value
|
||||
- Changed: Lacrosse V2 WS2300/WS3600 plugin number to get faster processing, changed various other parts as well
|
||||
- Changed: Lacrosse V1 pulse duration checks
|
||||
- Changed: various parts to improve speed
|
||||
- Changed: Flamingo Smoke detector signal re-transmits from 8 to 10 times
|
||||
- Added: Additional tests on Alecto V1 and Alecto V4 to filter out false positives
|
||||
- Fixed: AC (NewKaku) protocol send for some device numbers
|
||||
- Fixed: little bug in UPM code
|
||||
- Fixed: Oregon wind speed reporting
|
||||
- Fixed: Wind speed calculations
|
||||
- Fixed: Wind direction reporting in all plugins
|
||||
- Fixed: AlectoV3 humidity value displaying out of range values
|
||||
- Fixed: OregonV1 decoding
|
||||
|
||||
R25:
|
||||
- Fixed: Eurodomest address range check
|
||||
- Fixed: Alecto V1 and V3 humidity handling
|
||||
- Fixed: Lacrosse WS2300/WS3600 and labelled as LacrosseV2
|
||||
|
||||
R24:
|
||||
- Fixed: Flamingo Smoke Detector timings and device address usage
|
||||
- Fixed: Timing for Nexa/Jula Anslut
|
||||
|
||||
R23:
|
||||
- Changed: Alecto V1 temperature data filtering
|
||||
- Added: Alecto V1 battery status now shown for temperature sensors
|
||||
|
||||
R22:
|
||||
- Various additional tests and fixes after intensive tests
|
||||
- Added: Home Confort send and recognition by Domoticz
|
||||
|
||||
R21:
|
||||
- Re-Activated PIR & Door/Window sensors (plugin 60/61)
|
||||
|
||||
R20:
|
||||
- Switched to Arduino 1.6.5
|
||||
|
||||
R19:
|
||||
- Complete rewrite
|
||||
- Added: Home Confort Smart Home - TEL-010
|
||||
- Added: RGB LED Controller
|
||||
- Added: RL-02 Digital Doorbell
|
||||
- Added: Deltronic Doorbell
|
||||
- Added: Sartano 2606 remote & switch
|
||||
|
||||
r18:
|
||||
- Added Banggood SKU174397, Sako CH113, Homemart/Onemall FD030 and Blokker (Dake) 1730796 outdoor temperature sensor
|
||||
- Tested Okay: Promax RSL366T, Profile PR-44N & PR-47N
|
||||
- Fixed: LaCrosse humidity values are correctly displayed
|
||||
- Fixed: Humidity values that originate from slave Nodos are correctly displayed
|
||||
- Fixed: UPM/Esic insane temperature values are skipped
|
||||
- Removed Xiron & Auriol debug data
|
||||
- Tightened pulse range on various protocols to prevent false positives
|
||||
|
||||
r17:
|
||||
- Modified Oregon THGR228N code,
|
||||
- Modified Newkaku(AC) dim values,
|
||||
- Corrected support for KAKU door switches,
|
||||
- Fixed Nodo Slave sensors,
|
||||
- Improved speed and priorities so that group commands are properly transmitting
|
||||
|
||||
r16:
|
||||
- Fixed Aleco V1 temperature ID to match wind sensors
|
||||
- Fixed HomeEasy transmit
|
||||
- Added AC(NewKaku) dimmer support
|
||||
|
||||
r15:
|
||||
- Improved large packet translation
|
||||
|
||||
r14:
|
||||
- Changed Motion sensors (60/61)
|
||||
|
||||
r13:
|
||||
- Flamingo Smoke detector fix
|
||||
- Added Xiron sensor support
|
||||
|
||||
r11/12:
|
||||
- Mertik / Dru Send added
|
||||
|
||||
r10:
|
||||
- Added Auriol Z32171A
|
||||
|
||||
r9:
|
||||
- Fixed Kaku send with high device id's (P1 M1 etc)
|
||||
|
||||
r8:
|
||||
- Improved descriptions
|
||||
|
||||
r7:
|
||||
- Fixed Oregon RTGR328N ID and humidity format
|
||||
- Fixed UPM/Esic humidity format
|
||||
- Fixed Alecto humidity format
|
||||
|
||||
r6:
|
||||
- Fixed Auriol V2 plugin
|
||||
- Updated Auriol plugin
|
||||
- Fixed Lacrosse Humidity
|
||||
|
||||
r1/2/3/4/5:
|
||||
- Added X10 receive/transmit plugin
|
||||
- Minor changes & improvements
|
||||
|
||||
|
||||
Special thanks to:
|
||||
Alex, Benoit, Bert, Christophe, Deennoo, Emmanuel, Gerrit, Goran, Graeme, Jelle, John, Jonas, Marek, Mark, Martinus, Maurice,
|
||||
Paul, Pim, Remco, Richard, Rob, Sebastien, Thibaut, William
|
||||
and everyone who contributed with feedback, suggestions, debug data, tests etc.
|
|
@ -0,0 +1,233 @@
|
|||
============================================================================
|
||||
Nodo - RFLink supported devices list
|
||||
============================================================================
|
||||
Remote Controls and Electrical Switches / Dimmers etc.:
|
||||
-------------------------------------------------------
|
||||
ARC Protocol: (Send + Receive)
|
||||
- Klik Aan Klik Uit (Code Wheel)
|
||||
- Princeton PT2262
|
||||
- MOSDESIGN M3EB
|
||||
- Domia Lite
|
||||
- Intertechno
|
||||
- CoCo Technologies
|
||||
- Cogex
|
||||
- D-IO (Chacon)
|
||||
- Nexa
|
||||
- Düwi Terminal
|
||||
- Promax RSL366T
|
||||
- Conrad 640472, 640473, 640475, 640476
|
||||
- ME FLS 100
|
||||
- Profile PR-44N, PR-47N
|
||||
- Sartano 2606
|
||||
- Impuls
|
||||
- Elro AB400
|
||||
- Waveman
|
||||
- Elro Home Comfort AB600
|
||||
- (Elro) Home Control
|
||||
- Smarthome YC-4000B
|
||||
- Phenix YC-4000S
|
||||
- Pollin Funk-Dimmer HouseLight FD-UP001
|
||||
- Pollin Funk-Steckdosen-Set 2605
|
||||
- Conrad 646443 outlet sockets / RSL366R
|
||||
- Proteam HO1853
|
||||
- Velleman WRS3B
|
||||
- "Emil Lux"/LUX-Tools (Obi.de Art.Nr. 2087971)
|
||||
- Znane-01 switch set sold at Biedronka (Impuls clone)
|
||||
- Renkforce
|
||||
|
||||
Automatic Code Learning Protocols: (Send + Receive)
|
||||
- Klik Aan Klik Uit
|
||||
(All products, among others: AWMR210, AWMT230, AWMD250, AWST8800)
|
||||
- CoCo Technologies
|
||||
- Trust SmartHome
|
||||
- Nexa Jula Anslut
|
||||
(among others: 408-063, 408-064)
|
||||
- Home Easy EU (among others HE100, HE200, HE300, AB600/HE600, HE800)
|
||||
- Smartwares (SH5-TDR-K 10.037.17)
|
||||
|
||||
Others: (Send + Receive)
|
||||
- Home Easy (Code Wheel)
|
||||
- Unitec 48110 EIM 826 / 48111 EIM 821
|
||||
- Quigg GT-1000 RC / Quigg GT-FSI-08
|
||||
- Intertek Eurodomest 972080 (Protocol revision 1 & 2 - full autodetection)
|
||||
- Intertek Eurodomest 972086 (Protocol revision 1 & 2 - full autodetection)
|
||||
- Blyss
|
||||
- Conrad RSL2, Conrad RSL88R/B
|
||||
- Kambrook RF3399/RF3405/RF3672/RF3689/RF4471R
|
||||
- X10 RF switches
|
||||
- Home Confort Smart Home - Among others: TEL-010, PRF-100
|
||||
- Quigg GT-7008BS, Quigg GT-FSI-04
|
||||
- DMV-7008S
|
||||
- Mandolyn RC-710
|
||||
- Powerfix RCB-I 3600
|
||||
- Quigg GT-8000
|
||||
- Chacon (TR-502MSV, NR.RC402)
|
||||
- Rev Ritter REV 8342L
|
||||
- Ikea Koppla
|
||||
- TRC02 RGB Controller
|
||||
- Aster / GEMINI EMC/99/STI/037
|
||||
- Silvercrest l36-001
|
||||
- Brennenstuhl RCS 1000 N Comfort
|
||||
- Lidl / Libra TR502MSV
|
||||
|
||||
- Flamingo FA500R/S/DSS/WD
|
||||
- SilverCrest 91210/60494 RCS AAA3680
|
||||
- Mumbi M-FS300
|
||||
- Toom 1919384
|
||||
============================================================================
|
||||
Weather Sensors:
|
||||
----------------
|
||||
- Alecto V1:
|
||||
Alecto WS3500, SilverCrest, Otio SH-10, Otio SH-20
|
||||
Auriol H13726, Ventus WS155, Hama EWS 1500, Meteoscan W155/W160
|
||||
Alecto WS4500, Ventus W044, Balance RF-WS105
|
||||
- Alecto V2: (868 Mhz!)
|
||||
ACH2010, DKW2012
|
||||
- Alecto V3:
|
||||
WS1100, WS1200
|
||||
- Alecto V4:
|
||||
Banggood SKU174397, Sako CH113, Homemart/Onemall FD030 and Blokker (Dake) 1730796 outdoor temperature sensor
|
||||
- Cresta/Hideki:
|
||||
Hideki, TFA Nexus, Mebus, Irox, Irox-Pro X, Honeywell, Cresta TE923, TE923W, TE821W,
|
||||
WXR810, DV928, Ventus W906, HomeWizard Rain meter
|
||||
- Mebus:
|
||||
Mebus Outdoor Sensor
|
||||
Stacja Pogody WS-9941-M
|
||||
- UPM/Esic:
|
||||
UPM, Esic, Emos, DVM, Clas Ohlson, Dickson
|
||||
WT260,WT260H,WT440H,WT450,WT450H,WDS500,RG700
|
||||
- LaCrosse:
|
||||
Lacrosse TX3-TH Thermo/Humidity, Lacrosse TX4
|
||||
WS7000-15: Anemometer, WS7000-16: Rain precipitation, WS2500-19: Brightness Luxmeter,
|
||||
WS7000-20: Thermo/Humidity/Barometer, TFA 30.3125 (temperature + humidity), TFA 30.3120.90 (temperature)
|
||||
- LaCrosseV2:
|
||||
WS2300 (Temperature/Humidity/Wind/Rain), WS2310, WS2355, WS3600
|
||||
- Auriol:
|
||||
Z31743, Rubicson
|
||||
- Auriol V2:
|
||||
Z31055A-TX, Xiron, Watshome YT6018-2, Technoline
|
||||
- Auriol V3:
|
||||
Z32171A
|
||||
- FineOffset:
|
||||
Fine Offset Electronics WH2, Agimex Rosenborg 66796, ClimeMET CM9088
|
||||
- Eurochron:
|
||||
EAS 301Z / EAS 302
|
||||
- Prologue:
|
||||
Clas Ohlson 36-4741, Clas Ohlson 36-5087
|
||||
- Oregon V1/2/3:
|
||||
THC238, THC268, THN132N, THWR288A, THRN122N, THN122N, AW129, AW131, THGR268, THGR122X,
|
||||
THGN122N, THGN123N, THGR122NX, THGR228N, THGR238, WTGR800, THGR918, THGRN228NX, THGN500,
|
||||
THGR810, RTGR328N, THGR328N, Huger BTHR918, BTHR918N, BTHR968, RGR126, RGR682, RGR918, PCR122,
|
||||
THWR800, THR128, THR138, THC138, OWL CM119, cent-a-meter, OWL CM113, Electrisave, RGR928,
|
||||
UVN128, UV138, UVN800, Huger-STR918, WGR918, WGR800, PCR800, WGTR800, BTHG968, OWL CM180, BTHGN129
|
||||
============================================================================
|
||||
Pool/Water Thermometer
|
||||
Conrad 9771 Pool Thermometer
|
||||
============================================================================
|
||||
Soil : Temperature & Moisture/Humidity Sensors
|
||||
Imagintronix XH300 sensor
|
||||
TH12 Opus TX300
|
||||
============================================================================
|
||||
Dusk Sensors (Light On/Off detection):
|
||||
-----------------------------------
|
||||
KAKU ABST-604
|
||||
Home Easy HE863
|
||||
Intertechno ITDS-5
|
||||
============================================================================
|
||||
Window blinds/shutters/sun screens:
|
||||
-----------------------------------
|
||||
Kaku ASUN650
|
||||
Intertechno CMR-500, ITL-500, ITL-1000
|
||||
============================================================================
|
||||
Motion Detectors:
|
||||
--------------------------------
|
||||
Low Budget Chinese PIR (only signals motion detection)
|
||||
Aritech PIR (only signals motion detection)
|
||||
Ajax Chub Varel PIR (only signals motion detection)
|
||||
Chuango: among others PIR-900 PIR sensor
|
||||
Oregon Scientific NR868 PIR/night light
|
||||
Oregon Scientific MSR939 PIR
|
||||
============================================================================
|
||||
Door/Window sensors:
|
||||
--------------------------------
|
||||
Low Budget Chinese Door/Window detectors
|
||||
Intertechno ITM-100
|
||||
KAKU AMST-606 door/window sensor (separate signals for open and close)
|
||||
Home Easy HE852 (separate signals for open and close)
|
||||
CHACON DIO 54781 (separate signals for open and close)
|
||||
COCO (separate signals for open and close)
|
||||
Evology door/window contact sensor
|
||||
ELMES CTX3H, CTX4H
|
||||
Chuango: among others DWC-100 Door sensor, DWC-102 Door sensor
|
||||
============================================================================
|
||||
Fireplace:
|
||||
----------
|
||||
Mertik G6R H4T1 / Dru
|
||||
============================================================================
|
||||
Smoke Detectors:
|
||||
----------------
|
||||
KD101 (Send + Receive)
|
||||
Diamant Smoke alarm (Send + Receive)
|
||||
Flamingo FA20RF (Send + Receive)
|
||||
Chacon 34126 (Send + Receive)
|
||||
============================================================================
|
||||
Doorbells:
|
||||
----------
|
||||
SelectPlus (200689103 - Black - Date code:0614), 1 by One, Delta (O00 QH-0031) (Send + Receive)
|
||||
SelectPlus (200689101 - White - Date code:0914) (Send + Receive)
|
||||
KAKU ACDB 6500BC (Send + Receive)
|
||||
Deltronic Wireless Doorbell (Send + Receive)
|
||||
RL-02 Wireless Doorbell (Send + Receive)
|
||||
Byron SX (Send + Receive)
|
||||
SilverCrest Z31370-TX (Receive)
|
||||
Forrinx (Receive)
|
||||
Heidemann HX Silverline 70290 (Receive)
|
||||
L^Home model 32311T (Receive)
|
||||
Plieger York (Receive)
|
||||
Note that when the Plieger button is detected as Conrad RSL2, you need to use the button
|
||||
on the inside of the Plieger doorbell to change the address code of the Plieger.
|
||||
============================================================================
|
||||
Nodo Slave Sensors:
|
||||
-------------------
|
||||
Various Nodo sensor types are supported.
|
||||
Make sure you use Nodo Slave ID 1,2, 4 till 9 to make the sensor a separate sensor.
|
||||
If you want to have combined sensors (eg temperature + humidity in one device) make sure
|
||||
you use Nodo Slave ID 10 till 16
|
||||
|
||||
The following variable / sensor types are currently supported
|
||||
|
||||
Variabele 5 : Temperature
|
||||
Variabele 6 : Humidity
|
||||
Variabele 7 : Rain
|
||||
Variabele 8 : Wind speed
|
||||
Variabele 9 : Wind direction
|
||||
Variabele 10 : Wind gust
|
||||
Variable 11, 12 en 13 : Temperature
|
||||
Variable 14 : Humidity
|
||||
Variable 15 : UV
|
||||
Variable 16 : Barometric pressure
|
||||
|
||||
|
||||
Electricity/Water/Gas pulse meters are supported when using the following Nodo variable numbers:
|
||||
|
||||
Make sure the slave devices are using Nodo Slave ID 3 !!!
|
||||
|
||||
Variabele 1 : Pulse value 1
|
||||
Variabele 2 : Pulse value 2
|
||||
Variabele 3 : Pulse value 3
|
||||
Variabele 4 : Pulse value 4
|
||||
Variabele 5 : Pulse value 5
|
||||
Variabele 6 : Pulse value 6
|
||||
|
||||
If you require support for other sensors just let us know.
|
||||
============================================================================
|
||||
|
||||
Chuango
|
||||
* G5 GSM/SMS/RFID Touch Alarm System
|
||||
* DWC-100 Door sensor
|
||||
* DWC-102 Door sensor
|
||||
* KP-700 Wireless Keypad
|
||||
* PIR-900 PIR sensor
|
||||
* RC-80 Remote Control
|
||||
* SMK-500 Smoke sensor
|
||||
|
|
@ -0,0 +1,65 @@
|
|||
=====================================================================================================================================
|
||||
RFLINK GATEWAY LICENSE v1.0
|
||||
=====================================================================================================================================
|
||||
Arduino project "RFLink Gateway"
|
||||
|
||||
© Copyright 2015..2016 Stuntteam
|
||||
(Portions © Copyright 2010..2015 Paul Tonkes (some Nodo 3.7 code parts))
|
||||
|
||||
Documentation : http://sourceforge.net/projects/rflink/
|
||||
Questions/Suggestions etc. mail to : frankzirrone@gmail.com
|
||||
Compiler : http://arduino.cc
|
||||
=====================================================================================================================================
|
||||
LICENSE TERMS AND CONDITIONS
|
||||
|
||||
The RFLink distributed and pre-compiled code is made available free of charge and without any warranties.
|
||||
This License explicitly affirms your unlimited permission to run the unmodified Program.
|
||||
If someone made you pay for this program, contact us!
|
||||
|
||||
|
||||
The RFLink Gateway Source Code is made available so that third parties can develop their own plugins for the RFLink Gateway.
|
||||
Availability of the core code and functional sample plugins does not mean that each and every plugin will be open source.
|
||||
The fact that the code is published does not mean you obtain any kind of ownership or get any rights to the code.
|
||||
This License explicitly affirms that you have the right to use the source code as a development environment to create your
|
||||
own plugins which you can share with the community and project maintainers.
|
||||
When you publish your plugin with the community it automatically falls under this license. However, it is also possible to share your
|
||||
plugin with the project maintainers and keep your plugin closed source. In that case, the compiled portions of your code will
|
||||
automatically fall under this license. All contributors hold the copyright for their own work.
|
||||
The source code is free for use in any open source project when the original copyright notices, headers and this license file are included.
|
||||
This program is free software: you can redistribute it and/or modify it when the original copyright notices and headers are included.
|
||||
|
||||
You are not allowed to sell the pre-compiled code or the source code or distribute it without this license file.
|
||||
|
||||
Usage of any parts of this code in a commercial work is prohibited unless express written approval is granted!
|
||||
Some parts of the code might contain watermarking to identify our work.
|
||||
You are not allowed to decompile, disassemble or reverse engineer any parts of the pre-compiled program.
|
||||
|
||||
The license does not permit incorporating this program into proprietary programs.
|
||||
|
||||
Disclaimer of Warranty.
|
||||
This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
|
||||
The copyright holders provide the program "AS IS" without warranty of any kind, either expressed or implied, including, but not limited to,
|
||||
the implied warranties of merchantability or fitness for a particular purpose. The entire risk as to the quality and performance of the program
|
||||
is with you. Should the program prove defective, you assume the cost of all necessary servicing, repair or correction.
|
||||
|
||||
Limitation of Liability.
|
||||
In no event unless required by applicable law or agreed to in writing will any copyright holder, or any other party who modifies and/or conveys
|
||||
the program as permitted above, be liable to you for damages, including any general, special, incidental or consequential damages arising out of the
|
||||
ues or inability to use the program (including but not limited to loss of data being rendered inaccurate or losses sustained by you or third
|
||||
parties or a failure of the program to operate with any other programs), even if such holder or other party has been advised of the possibility of
|
||||
such damages.
|
||||
-------------------------------------------------------------------------------------------------------------------------------------
|
||||
Warning:
|
||||
The RFLink Gateway should not be used in any life-threatening situations.
|
||||
|
||||
The RFLink Gateway is NOT justified to be used as a main part of a primary alarm system.
|
||||
RFLink may only be used to listen to alarm sensors or activate a siren to complement a home automation system.
|
||||
Note that if you own an alarm system which RFLink could disarm by broadcasting a recorded signal, it is time to upgrade your alarm system.
|
||||
-------------------------------------------------------------------------------------------------------------------------------------
|
||||
Installation information:
|
||||
|
||||
All files should be located in a directory named "RFLink".
|
||||
Install the Arduino compiler. You can download the compiler at www.arduino.cc
|
||||
Preffered is 1.6.5 or similar
|
||||
Open from the Arduino IDE the file RFlink.ino
|
||||
-------------------------------------------------------------------------------------------------------------------------------------
|
|
@ -0,0 +1,78 @@
|
|||
/*********************************************************************************************\
|
||||
* Convert HEX or DEC tring to unsigned long HEX, DEC
|
||||
\*********************************************************************************************/
|
||||
unsigned long str2int(char *string) {
|
||||
return(strtoul(string,NULL,0));
|
||||
}
|
||||
/*********************************************************************************************\
|
||||
* Convert string to command code
|
||||
\*********************************************************************************************/
|
||||
int str2cmd(char *command) {
|
||||
if(strcasecmp(command,"ON") == 0) return VALUE_ON;
|
||||
if(strcasecmp(command,"OFF") == 0) return VALUE_OFF;
|
||||
if(strcasecmp(command,"ALLON") == 0) return VALUE_ALLON;
|
||||
if(strcasecmp(command,"ALLOFF") == 0) return VALUE_ALLOFF;
|
||||
if(strcasecmp(command,"PAIR") == 0) return VALUE_PAIR;
|
||||
if(strcasecmp(command,"DIM") == 0) return VALUE_DIM;
|
||||
if(strcasecmp(command,"BRIGHT") == 0) return VALUE_BRIGHT;
|
||||
if(strcasecmp(command,"UP") == 0) return VALUE_UP;
|
||||
if(strcasecmp(command,"DOWN") == 0) return VALUE_DOWN;
|
||||
if(strcasecmp(command,"STOP") == 0) return VALUE_STOP;
|
||||
if(strcasecmp(command,"CONFIRM") == 0) return VALUE_CONFIRM;
|
||||
if(strcasecmp(command,"LIMIT") == 0) return VALUE_LIMIT;
|
||||
return false;
|
||||
}
|
||||
/********************************************************************************************\
|
||||
* Convert unsigned long to float long through memory
|
||||
\*********************************************************************************************/
|
||||
float ul2float(unsigned long ul) {
|
||||
float f;
|
||||
memcpy(&f, &ul,4);
|
||||
return f;
|
||||
}
|
||||
/*********************************************************************************************/
|
||||
void PrintHex8(uint8_t *data, uint8_t length) { // prints 8-bit data in hex (lowercase)
|
||||
char tmp[length*2+1];
|
||||
byte first ;
|
||||
int j=0;
|
||||
for (uint8_t i=0; i<length; i++) {
|
||||
first = (data[i] >> 4) | 48;
|
||||
if (first > 57) tmp[j] = first + (byte)39;
|
||||
else tmp[j] = first ;
|
||||
j++;
|
||||
|
||||
first = (data[i] & 0x0F) | 48;
|
||||
if (first > 57) tmp[j] = first + (byte)39;
|
||||
else tmp[j] = first;
|
||||
j++;
|
||||
}
|
||||
tmp[length*2] = 0;
|
||||
Serial.print(tmp);
|
||||
}
|
||||
/*********************************************************************************************/
|
||||
// todo: make uppercase? 3a = 3 or 48 (0x30) = 0x33 >57 (0x39) a>3a >39 > +27
|
||||
void PrintHexByte(uint8_t data) { // prints 8-bit value in hex (single byte)
|
||||
char tmp[3];
|
||||
byte first ;
|
||||
first = (data >> 4) | 48; // or with 0x30
|
||||
if (first > 57) tmp[0] = first + (byte)7; // 39; // if > 0x39 add 0x27
|
||||
else tmp[0] = first ;
|
||||
|
||||
first = (data & 0x0F) | 48;
|
||||
if (first > 57) tmp[1] = first + (byte)7; // 39;
|
||||
else tmp[1] = first;
|
||||
tmp[2] = 0;
|
||||
Serial.print(tmp);
|
||||
}
|
||||
/*********************************************************************************************/
|
||||
// Reverse all bits in a byte
|
||||
byte reverseBits(byte data) {
|
||||
byte b = data;
|
||||
for (byte i = 0; i < 8; ++i) {
|
||||
data = (data << 1) | (b & 1);
|
||||
b >>= 1;
|
||||
}
|
||||
return data;
|
||||
}
|
||||
/*********************************************************************************************/
|
||||
|
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,617 @@
|
|||
//#######################################################################################################
|
||||
//## This Plugin is only for use with the RFLink software package ##
|
||||
//## Plugin-01: Long Packet Translation and debugging ##
|
||||
//#######################################################################################################
|
||||
/*********************************************************************************************\
|
||||
* This plugin takes care of long packets that actually contain multiple RF packets
|
||||
* Usually caused by a very short delay between RF packets
|
||||
*
|
||||
* Author : StuntTeam
|
||||
* 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!
|
||||
***********************************************************************************************
|
||||
* Technical information:
|
||||
*
|
||||
* The first part of this plugin outputs all the received pulses from RF packets, use this plugin to
|
||||
* find signals from new devices. Even if you do not know what to do with the data yourself you might
|
||||
* want to share your data so others can analyse it and add support for missong protocols.
|
||||
*
|
||||
* The second part of this plugin takes care of oversized RF packets that might need to be cut into
|
||||
* smaller RF packets. Usually the oversized packets are due to a very short delay between re-transmits
|
||||
* so that multiple packets are seen as one long packet
|
||||
*
|
||||
* ELRO HOMEEASY HE842
|
||||
* The HE842 remote control sends 3 different protocols.
|
||||
* 8 x Protocol method 1 - 28 bit code (58 pulses)
|
||||
* 20 x Protocol method 2 - 24 bit code (50 pulses)
|
||||
* 6 x Protocol method 3 - HE compatible (116 pulses) See Plugin 15
|
||||
|
||||
* Method 1 is detected as a 460+ pulse RF packet which we reject.
|
||||
* 20;19;DEBUG;Pulses=464;Pulses(uSec)=275,950,200,925,850,275,200,925,200,925,850,275,200,925,850,275,200,925,200,925,850,275,200,925,200,925,850,275,850,275,200,925,200,925,850,275,200,925,200,925,200,925,850,275,200,925,850,275,850,275,200,925,850,275,200,925,200,4975,200,925,200,925,850,275,200,925,200,925,850,275,200,925,850,275,200,925,200,925,850,275,200,925,200,925,850,275,850,275,200,925,200,925,850,275,200,925,200,925,200,925,850,275,200,925,850,275,850,275,200,925,850,275,200,925,200,4975,200,925,200,925,850,275,200,925,200,925,850,275,200,925,850,275,200,925,200,925,850,275,200,925,200,925,850,275,850,275,200,925,200,925,850,275,200,925,200,925,200,925,850,275,200,925,850,275,850,275,200,925,850,275,200,925,200,4975,200,925,200,925,850,275,200,925,200,925,850,275,200,925,850,275,200,925,200,925,850,275,200,925,200,925,850,275,850,275,200,925,200,925,850,275,200,925,200,925,200,925,850,275,200,925,850,275,850,275,200,925,850,275,200,925,200,4975,200,925,200,925,850,275,200,925,200,950,850,275,200,925,850,275,200,925,200,925,850,275,200,925,200,925,850,275,850,275,200,925,200,925,850,275,200,925,200,925,200,925,850,275,200,925,850,275,850,275,200,925,850,275,200,925,200,4975,200,950,225,950,850,275,200,925,200,925,850,275,200,925,850,275,200,925,200,925,850,275,200,925,200,925,850,275,850,275,200,925,200,925,850,275,200,925,200,925,200,925,850,275,200,925,850,275,850,275,200,925,850,275,200,925,200,4975,200,925,200,925,850,275,200,925,200,925,850,275,200,925,850,275,200,925,200,925,850,275,200,925,200,925,850,275,850,275,200,925,200,925,850,275,200,925,200,925,200,925,850,275,200,925,850,275,850,275,200,925,850,275,200,925,200,4975,200,925,200,925,850,275,200,925,200,925,850,275,200,925,850,275,200,925,200,925,850,275,200,925,200,925,850,275,850,275,200,925,200,925,850,275,200,925,200,925,200,925,850,275,200,925,850,275,850,275,200,925,850,275,200,975,200;
|
||||
* -------------------
|
||||
* ELRO FLAMINGO FA500
|
||||
* The FA500R remote control sends 4 different protocols.
|
||||
* 4 x Protocol method 1 - 28 bit code (58 pulses) - Same as HE842 Method 1
|
||||
* 3 x Protocol method 2 - AC compatible (132 pulses)
|
||||
* 3 x Protocol method 3 - HE compatible (116 pulses)
|
||||
* 5 x Protocol method 4 - 24/12 bit code (24 pulses)
|
||||
* It appears that the FA500S power switch is only capable to react to the first method!
|
||||
* RFLink can only distinguish the 3rd method properly. Method 1 and 2 have to be pulled apart first.
|
||||
* This plugin will split the received signal so that method 1 or 2 can be used.
|
||||
* In this case we force method 1 so that the remote control can be used with the FA500 switches.
|
||||
* Method 3: 20;60;DEBUG;Pulses=24;Pulses(uSec)=325,800,275,800,825,225,275,800,275,825,275,800,825,225,275,800,825,225,275,800,275,800,275;
|
||||
* Method 1&2: 20;1F;DEBUG;Pulses=364;Pulses(uSec)=225,4650,200,875,200,875,800,250,200,875,200,875,800,250,200,875,200,875,825,250,825,250,200,875,825,250,200,875,200,875,825,250,800,250,200,875,200,875,200,875,800,250,800,225,200,875,200,875,825,250,825,250,200,875,800,250,200,875,200,4650,200,875,200,875,825,250,200,875,200,875,800,250,200,875,200,875,825,250,800,250,200,875,800,250,200,875,200,875,825,225,825,250,200,875,200,875,200,875,825,250,800,250,200,875,200,875,825,250,800,225,200,875,800,250,200,875,200,4650,200,875,200,875,800,250,200,875,200,875,825,250,200,875,200,875,800,250,825,250,200,875,800,250,200,875,200,875,800,225,825,250,200,875,200,875,200,875,800,250,800,250,200,875,200,875,800,250,825,225,200,875,800,250,200,875,200,4650,200,875,200,875,800,250,200,875,200,875,800,250,200,875,200,875,825,250,800,250,200,875,825,250,200,875,200,875,800,225,800,250,200,875,200,875,200,875,800,250,825,250,200,875,200,875,800,250,800,250,200,875,825,250,200,875,150,2550,150,175,150,1200,125,175,150,1200,125,175,150,1175,150,175,150,1175,150,175,150,1175,150,175,150,1175,150,175,150,1175,150,175,150,1175,150,175,150,1200,150,1175,150,200,150,175,150,1200,150,175,150,1175,150,175,150,1200,150,1175,150,200,150,1175,150,200,150,175,150,1175,150,1175,150,200,150,1175,150,200,125,175,150,1175,150,175,150,1175,150,175,150,1175,150,175,150,1175,150,175,150,1175,150,175,150,1175,150,175,125,1200,150,175,125,1200,150,175,150,1200,150,175,150,1200,150,175,150,1200,150,175,150,1200,150,175,150,1200,150,1175,150,175,150;
|
||||
* 20;55;DEBUG;Pulses=58;Pulses(uSec)=275,900,200,900,850,250,200,925,200,925,850,275,875,250,225,950,875,275,875,275,225,950,875,275,225,950,875,275,225,950,225,950,875,275,200,950,875,275,875,275,875,250,875,275,875,275,875,275,875,250,225,950,875,275,200,950,225;
|
||||
* 20;57;DEBUG;Pulses=130;Pulses(uSec)=225,200,150,1250,150,200,150,1250,150,200,150,1250,150,200,150,1250,150,200,150,1275,150,200,150,1300,150,200,150,1300,150,200,150,1300,150,200,150,1300,150,1275,150,225,150,200,150,1300,150,200,150,1300,150,200,150,1300,150,1275,150,225,150,1300,150,225,150,200,150,1300,150,1300,150,200,150,1300,150,200,150,200,150,1300,150,200,150,1300,150,200,150,1300,150,200,150,1300,150,200,150,1300,150,200,150,1300,150,200,150,1300,150,200,150,1300,150,200,150,1300,150,200,150,1300,150,200,150,1300,150,200,150,1300,150,200,150,1300,150,1275,150,200,150;
|
||||
* 20;59;DEBUG;Pulses=124;Pulses(uSec)=225,1250,150,175,150,1250,150,200,150,1250,150,200,150,1250,150,200,150,1250,150,200,150,1300,150,200,150,1300,150,200,150,1300,150,1300,150,200,150,200,150,1300,150,200,150,1300,150,200,150,1300,150,1275,150,225,150,1275,150,225,150,200,150,1300,150,1275,150,200,150,1275,150,200,150,200,150,1300,150,200,150,1300,150,200,150,1300,150,200,150,1300,150,200,150,1300,150,200,150,1300,150,200,150,1300,150,200,150,1300,150,200,150,1300,150,200,150,1300,150,200,150,1300,150,200,150,1300,150,200,150,1300,150,1275,150,200,150;
|
||||
* -------------------
|
||||
* Auriol
|
||||
* 20;03;DEBUG;Pulses=511;Pulses(uSec)=425,750,425,775,425,1700,450,1700,450,1675,450,1700,450,750,425,1725,425,1725,425,775,425,800,400,800,400,800,425,800,400,800,425,800,400,1725,400,1750,425,800,400,1750,400,800,400,1750,400,825,400,1750,400,1750,400,1750,400,1750,400,1750,400,800,400,825,400,800,400,825,400,825,400,825,375,825,400,825,400,3725,300,825,400,825,400,1750,400,1750,400,1750,400,1750,400,825,400,1750,400,1750,375,825,400,825,400,825,400,825,400,825,375,825,400,825,375,1750,400,1775,400,825,375,1775,400,825,375,1750,400,825,400,1750,375,1775,400,1750,375,1775,400,1750,400,825,400,825,400,825,400,825,400,825,400,825,400,825,400,825,400,3725,300,825,400,825,400,1750,400,1750,400,1775,400,1750,400,825,400,1750,400,1750,375,825,400,825,400,825,400,825,400,825,400,825,400,825,400,1750,400,1750,400,825,400,1775,400,825,375,1775,400,825,375,1750,375,1750,400,1775,400,1750,400,1775,400,825,375,825,400,825,375,825,400,825,375,825,375,825,400,825,400,3725,275,825,375,825,400,1775,400,1775,375,1750,400,1775,375,825,375,1750,400,1775,400,825,400,825,375,825,400,825,400,825,375,825,400,825,375,1750,400,1775,400,825,375,1775,400,825,375,1750,400,825,375,1775,375,1775,400,1750,375,1775,400,1750,400,825,375,825,400,825,375,825,400,825,375,825,375,825,400,825,375,3750,300,825,375,825,400,1750,400,1775,375,1775,400,1750,375,825,375,1775,400,1775,375,825,400,825,375,825,400,825,400,825,375,825,400,825,375,1775,400,1750,375,825,400,1750,400,825,375,1775,400,825,375,1775,375,1750,400,1775,375,1750,400,1775,400,825,375,825,400,825,375,825,400,825,375,825,400,850,400,825,375,3750,275,825,375,825,400,1775,375,1775,375,1750,400,1775,375,825,400,1775,400,1750,400,825,375,825,375,825,375,850,400,825,375,825,400,825,375,1750,375,1775,375,825,375,1775,375,825,400,1750,400,825,375,1750,375,1775,375,1750,375,1775,400,1775,400,825,375,825,375,825,375,825,400,825,375,825,400,825,400,825,375,3750,275,825,375,825,400,1775,400,1750,375,1775,400,1775,375,825,400,1750,400,1775,400,825,400,825,375,825,400,825,400,825,375,825,400,825,375,1750,400,1775,375,825,375,1775,400,825,375,1750,400,825,375,1775,375,1775,400,1750,375,1775,375,1750,400,825,375,850,375,825,375,825,375,825;
|
||||
* -------------------
|
||||
* Xiron
|
||||
* 20;03;DEBUG;Pulses=511;Pulses(uSec)=600,3425,575,625,550,1600,525,1625,525,700,500,1650,500,1650,475,1675,475,725,475,1650,475,750,475,725,475,750,450,750,475,750,450,750,450,750,450,1700,450,1700,450,750,450,1700,450,750,450,1700,450,1700,450,1700,450,1700,450,1700,450,1700,450,1700,450,775,450,775,450,1700,425,1725,425,775,450,1700,425,775,450,800,425,3575,425,775,450,1700,425,1725,425,775,425,1700,450,1725,450,1700,425,775,425,1725,450,775,425,775,425,775,425,775,425,775,425,775,450,775,425,1700,425,1725,425,775,425,1725,425,775,425,1725,425,1700,450,1700,425,1725,450,1700,450,1725,425,1700,425,775,450,775,425,1725,425,1700,425,775,425,1725,450,775,425,775,425,3600,425,775,450,1725,425,1700,425,775,450,1725,425,1700,425,1725,450,775,450,1700,450,775,425,775,425,775,450,775,425,775,425,775,425,775,425,1725,425,1700,425,775,425,1725,425,775,425,1725,425,1700,425,1725,425,1700,425,1725,450,1700,425,1725,425,775,450,775,425,1700,425,1725,425,775,425,1725,450,775,425,775,425,3575,450,775,425,1700,425,1725,425,775,425,1700,425,1725,425,1700,450,775,450,1700,450,775,450,775,425,775,425,775,450,775,425,775,425,775,425,1700,425,1725,425,775,425,1700,450,775,425,1700,450,1700,425,1700,450,1700,425,1700,425,1700,450,1700,425,775,450,775,450,1700,425,1700,450,775,425,1700,450,775,425,775,425,3600,450,775,425,1725,450,1700,450,775,450,1700,450,1700,450,1700,450,775,450,1725,450,750,450,775,425,775,450,775,425,775,425,775,450,775,425,1725,450,1700,425,800,450,1700,425,775,425,1725,425,1700,425,1725,425,1700,450,1725,425,1700,450,1725,425,775,425,775,425,1700,450,1700,450,775,425,1725,425,775,450,775,425,3575,450,775,425,1700,425,1700,450,775,425,1700,450,1700,450,1700,450,775,450,1700,425,775,450,775,425,775,450,775,425,775,425,775,425,775,425,1700,450,1950,425,800,425,1700,425,775,425,1725,450,1700,425,1725,450,1700,450,1725,425,1700,450,1725,425,775,450,775,425,1700,450,1700,450,775,425,1725,450,775,425,775,425,3575,450,775,425,1700,425,1700,450,775,425,1700,450,1700,425,1700,450,775,450,1700,425,775,450,775,425,775,450,775,425,775,425,800,425,775,425,1700,450,1725,425,775,425,1725,425,775,425,1700,425,1725,425,1700,425,1725,450,1700,425,1725,450,1700,450,775,425,775,450,1700,425,1700;
|
||||
|
||||
* 20;06;DEBUG;Pulses=511;Pulses(uSec)=525,3475,525,700,475,1650,475,1675,475,750,450,1700,475,1675,450,1700,450,750,450,1700,425,775,425,775,400,825,400,800,425,800,425,800,400,1750,400,800,400,800,400,825,400,800,400,800,375,1750,400,825,375,825,400,1775,375,1750,400,1750,400,1750,400,825,400,825,400,1750,400,825,400,1750,400,1750,400,1775,375,1775,400,3625,400,825,400,1775,375,1775,400,825,375,1775,400,1750,400,1750,400,825,400,1750,375,825,400,825,400,825,375,825,400,825,375,825,375,1775,375,825,375,850,375,825,375,825,400,825,375,1775,375,825,375,850,350,1775,375,1775,375,1750,400,1775,350,825,375,825,375,1750,375,825,400,1750,375,1775,375,1775,375,1775,375,3650,375,850,375,1775,375,1775,400,825,375,1775,375,1750,400,1775,375,825,375,1775,375,825,375,825,400,850,375,825,400,825,375,825,400,1750,375,825,375,825,375,825,375,825,375,825,350,1775,375,825,375,850,350,1775,375,1775,375,1775,375,1775,375,825,375,825,375,1775,375,825,375,1775,375,1775,375,1775,375,1775,375,3625,400,825,375,1775,375,1750,400,825,375,1775,375,1750,400,1775,375,825,375,1775,375,825,375,825,375,825,375,850,375,825,375,825,375,1750,375,825,375,825,375,850,375,825,375,825,375,1775,375,850,375,825,350,1775,375,1750,375,1800,350,1775,375,825,375,825,375,1775,375,825,375,1775,375,1775,350,1775,375,1750,375,3650,375,825,375,1775,375,1750,400,825,400,1750,375,1775,375,1775,375,850,375,1775,375,825,375,825,400,825,375,825,375,825,375,825,375,1750,375,825,375,825,375,825,350,825,375,825,375,1775,375,825,375,825,350,1775,375,1775,375,1775,375,1775,375,850,350,825,375,1775,375,825,375,1775,375,1775,350,1775,375,1775,375,3650,375,825,375,1775,375,1775,375,825,375,1750,375,1775,375,1775,375,825,375,1775,375,850,350,825,375,825,375,825,375,850,375,850,375,1775,375,825,375,825,375,850,350,825,375,825,375,1775,375,825,375,1075,375,1775,375,1775,375,1775,375,1750,375,825,375,825,375,1775,375,825,375,1775,375,1775,375,1750,400,1775,375,3650,375,825,400,1775,375,1775,375,825,375,1775,375,1775,400,1750,375,825,400,1750,375,825,375,825,375,825,375,825,400,825,375,825,375,1775,375,825,350,825,375,825,375,825,375,850,350,1775,375,850,375,825,375,1775,375,1800,350,1775,375,1750,375,825,375,825,375,1775,375,825;
|
||||
* 20;0F;DEBUG;Pulses=511;Pulses(uSec)=475,3525,450,775,450,1700,425,1725,425,775,425,1725,425,1725,400,1775,400,825,400,1750,400,825,400,825,375,825,375,825,375,825,375,825,375,1775,375,850,375,850,350,850,350,850,375,1775,375,1775,375,850,375,850,350,1800,375,1775,375,1775,375,1775,350,850,375,850,350,1800,375,1775,375,1775,350,850,350,875,350,1800,350,3675,350,850,350,1775,375,1775,350,850,375,1775,350,1800,350,1775,375,850,350,1800,350,850,350,875,350,850,350,850,325,875,350,875,350,1800,350,875,350,875,325,875,350,850,350,1800,350,1800,350,875,350,875,350,1825,325,1800,350,1800,350,1800,350,875,350,875,325,1800,350,1800,350,1800,350,875,350,875,350,1800,350,3675,350,875,350,1800,350,1800,350,875,325,1800,350,1800,350,1800,350,875,350,1800,350,850,350,850,350,875,350,875,325,875,350,875,350,1800,350,875,350,875,325,875,350,875,350,1800,350,1800,350,875,350,850,350,1800,325,1825,350,1800,350,1800,350,850,350,875,325,1825,325,1800,350,1800,350,875,350,875,350,1825,325,3675,350,875,350,1800,350,1800,350,850,325,1800,350,1800,350,1800,350,875,350,1800,350,850,350,875,350,850,350,850,350,875,350,875,350,1800,350,875,350,875,325,875,350,875,350,1800,350,1800,350,875,325,875,350,1825,325,1825,325,1825,350,1800,350,875,350,875,350,1800,350,1800,350,1800,325,875,350,875,350,1800,350,3675,350,875,325,1800,350,1800,375,850,325,1800,350,1800,350,1800,350,850,350,1800,325,875,350,875,350,875,350,875,350,875,350,850,350,1800,350,875,350,875,350,875,350,875,350,1800,325,1825,350,875,325,875,350,1800,350,1800,325,1800,350,1800,350,875,350,875,350,1800,350,1800,350,1800,325,875,350,875,350,1800,350,3675,350,875,325,1800,350,1800,350,875,350,1800,350,1800,350,1800,350,850,350,1800,350,850,350,875,350,875,350,875,350,875,350,875,350,1825,350,875,350,875,350,875,350,875,350,1825,325,1800,350,1325,350,875,350,1800,350,1800,350,1800,350,1800,350,875,350,875,350,1800,350,1800,325,1800,350,875,350,875,350,1800,350,3675,350,850,350,1800,350,1800,350,875,350,1800,350,1800,350,1800,350,875,325,1800,350,850,350,850,350,875,350,850,350,850,350,875,325,1800,350,875,350,875,350,875,350,875,325,1800,350,1800,350,875,350,875,350,1800,350,1800,350,1800,350,1800,325,875,350,875,350,1800,350,1800; * -------------------
|
||||
* 20;0B;DEBUG;Pulses=511;Pulses(uSec)=75,125,625,3375,525,675,525,1625,475,725,475,750,475,750,450,775,450,1700,450,1700,450,1700,450,750,450,775,450,1725,425,800,425,800,425,800,425,1725,400,825,400,800,400,1725,425,800,425,775,425,800,400,800,400,800,400,1750,400,1750,400,1750,400,1750,400,825,400,1750,400,800,400,800,400,800,400,1750,400,1750,400,825,400,3625,400,800,400,1750,400,800,400,825,400,825,400,825,375,1775,375,1750,400,1750,375,800,400,800,400,1750,400,825,400,800,400,825,375,1775,375,825,375,825,375,1775,375,825,375,825,375,825,400,825,400,825,400,1750,400,1750,400,1750,375,1775,375,850,375,1775,375,825,375,825,375,825,375,1750,400,1750,400,825,400,3625,400,825,375,1775,375,825,400,825,400,825,400,825,400,1750,375,1775,375,1775,375,825,375,825,375,1775,375,825,375,825,375,825,400,1750,400,825,400,825,400,1750,375,825,375,825,375,825,375,825,375,825,375,1775,375,1775,375,1750,400,1750,400,825,400,1750,400,825,375,850,375,825,375,1775,375,1775,375,825,375,3650,375,825,375,1775,375,825,375,825,375,825,375,825,375,1750,400,1750,400,1750,375,825,400,825,375,1775,375,825,375,825,375,825,375,1775,375,825,375,825,375,1775,400,825,400,825,400,825,400,825,375,850,375,1775,375,1775,375,1775,375,1775,375,825,375,1775,375,825,400,825,400,825,400,1750,400,1750,375,850,375,3650,400,825,400,1750,400,825,400,825,375,825,375,825,375,1775,375,1775,375,1775,375,825,375,850,375,1750,400,825,400,825,400,825,400,1750,375,825,375,825,375,1775,375,825,375,825,375,825,375,825,375,825,400,1750,400,1775,400,1750,400,1750,375,825,375,1775,375,850,375,825,375,825,375,1775,375,1775,375,825,400,3625,400,825,375,1775,400,825,375,825,375,825,400,825,400,1750,400,1750,400,1750,375,825,375,825,375,1775,375,825,375,825,375,825,375,1775,375,825,400,825,400,1750,400,825,400,825,375,850,375,825,375,825,375,1775,375,1775,375,1775,375,1775,375,800,400,1750,400,1300,375,825,400,825,400,1750,400,1750,400,825,375,3650,375,825,400,1750,400,825,400,825,400,825,375,825,375,1775,375,1775,375,1775,375,850,375,850,375,1775,375,825,400,825,375,825,400,1750,400,825,400,825,375,1775,375,825,375,825,375,850,375,825,375,825,375,1775,375,1750,400,1750,400,1750,400,825,400,1750,375,825;
|
||||
* 20;17;DEBUG;Pulses=511;Pulses(uSec)=550,675,475,1650,525,700,500,700,450,750,450,750,450,1700,450,1700,450,1725,400,775,425,775,425,1725,400,800,425,800,400,775,425,1725,400,800,400,825,400,1750,400,800,425,800,400,825,400,1775,400,825,400,1750,400,1750,400,1750,400,1750,400,800,400,825,400,1775,375,825,400,1750,375,825,375,825,400,825,375,3625,400,825,400,1750,375,825,400,825,375,825,375,825,375,1775,350,1775,375,1775,375,825,400,825,375,1775,375,850,375,825,400,825,400,1775,375,850,375,850,375,1775,375,825,375,850,375,850,375,1775,375,825,375,1775,375,1775,375,1750,400,1775,400,825,375,850,375,1775,375,825,400,1775,375,850,375,850,375,825,375,3650,375,825,375,1775,375,850,375,850,375,825,400,825,375,1750,375,1775,375,1775,375,825,400,825,375,1775,375,850,375,825,375,825,375,1775,375,850,375,850,375,1775,375,825,375,850,375,850,375,1775,375,825,375,1775,375,1800,375,1775,400,1775,375,850,375,850,375,1775,375,825,375,1775,375,850,375,850,375,825,375,3650,375,825,375,1775,375,850,375,850,375,825,400,825,375,1775,375,1775,375,1775,375,825,400,825,350,1775,375,850,375,825,375,825,375,1775,350,850,375,850,350,1775,375,825,375,850,375,850,375,1775,375,825,375,1775,375,1775,375,1775,375,1775,375,825,375,850,375,1775,375,825,375,1775,375,850,375,850,375,850,375,3650,375,825,375,1775,375,825,375,850,375,850,375,825,375,1775,375,1775,375,1800,375,825,375,825,375,1775,375,850,375,825,375,825,375,1775,350,850,375,850,350,1775,375,825,375,850,350,850,375,1800,375,825,375,1775,350,1800,350,1800,375,1775,375,825,375,850,350,1800,375,825,375,1775,350,850,375,850,375,850,375,3650,375,825,375,1775,375,850,375,850,350,850,375,850,375,1775,375,1775,350,1800,375,825,375,825,375,1775,375,850,375,850,375,825,375,1775,350,850,375,850,375,1775,375,825,375,825,375,850,375,1800,375,825,375,1775,375,1800,350,1775,375,1775,375,825,375,850,375,2025,375,850,375,1775,400,825,375,850,375,850,375,3650,375,850,375,1775,400,825,350,850,375,850,375,850,375,1775,375,1775,375,1775,375,850,350,825,375,1775,375,850,375,850,375,825,375,1775,375,825,375,850,375,1800,375,825,375,825,375,825,350,1800,375,850,375,1775,375,1775,375,1775,375,1775,375,825,375,825,375,1775,375,850,375,1775;
|
||||
auriol..
|
||||
* BYRON & LIDL doorbells
|
||||
* The doorbells send the same packet a number of times shortly after each other.
|
||||
* We just grab one packet out of the lot and kill the remaining ones.
|
||||
* -------------------
|
||||
* Home Confort Smart Home - TEL-010
|
||||
* The Home Confort remote sends the same RF packet at least 6 times over the air. The delay in between the re-transmits is too short to detect individual packets
|
||||
* So we break, filter and convert the Home Confort RF packets in this plugin
|
||||
\*********************************************************************************************/
|
||||
#define OVERSIZED_LIMIT 291 // longest packet is handled by plugin 48
|
||||
|
||||
#define PULSE500 500/RAWSIGNAL_SAMPLE_RATE
|
||||
#define PULSE1100 1100/RAWSIGNAL_SAMPLE_RATE
|
||||
#define PULSE1600 1600/RAWSIGNAL_SAMPLE_RATE
|
||||
#define PULSE2000 2000/RAWSIGNAL_SAMPLE_RATE
|
||||
#define PULSE4000 4000/RAWSIGNAL_SAMPLE_RATE
|
||||
#define PULSE4200 4200/RAWSIGNAL_SAMPLE_RATE
|
||||
#define PULSE3300 3300/RAWSIGNAL_SAMPLE_RATE
|
||||
#define PULSE2500 2500/RAWSIGNAL_SAMPLE_RATE
|
||||
#define PULSE3000 3000/RAWSIGNAL_SAMPLE_RATE
|
||||
#define PULSE5000 5000/RAWSIGNAL_SAMPLE_RATE
|
||||
#define PULSE6000 6000/RAWSIGNAL_SAMPLE_RATE
|
||||
#define PULSE6500 6500/RAWSIGNAL_SAMPLE_RATE
|
||||
|
||||
#ifdef PLUGIN_001
|
||||
boolean Plugin_001(byte function, char *string) {
|
||||
byte HEconversiontype=1; // 0=No conversion, 1=conversion to Elro 58 pulse protocol (same as FA500R Method 1)
|
||||
|
||||
int i,j;
|
||||
// ==========================================================================
|
||||
// TEST
|
||||
// ==========================================================================
|
||||
//PROGMEM int temp[]={4200,625,150,625,150,625,125,625,125,625,125,625,125,625,125,625,125,625,125,625,125,625,125,625,125,625,125,625,125,625,125,625,150,625,125,625,125,650,125,175,600,175,600,175,600,175,600,175,600,175,575,175,575,175,600,175,600,175,600,175,575,175,575,175,600,175,600,175,600,175,600,175,600,175,600,175,575,175,575,175,575,650,100,175,575,175,575,175,575,175,575,175,575,175,575,650,100,175,100,4625,2375,650,100,650,100,675,100,650,100,675,100,650,100,675,100,675,100,675,100,675,100,650,100,650,100,650,100,650,125,650,100,650,125,650,100,650,100,650,100,175,575,175,575,175,575,175,575,175,575,175,575,175,575,200,575,175,575,175,575,175,575,175,575,200,575,200,575,200,575,200,575,200,575,175,575,200,575,200,575,200,575,675,100,200,575,200,575,200,575,200,575,200,575,175,575,675,100,175,100,4625,2375,650,100,650,100,650,100,650,100,650,100,650,100,650,100,650,100,650,100,650,100,650,100,650,100,650,100,650,100,650,100,650,100,650,100,650,100,650,100,175,575,200,575,175,575,200,575,200,575,200,575,175,575,175,575,200,575,200,575,175,575,175,575,175,575,175,575,175,575,175,575,175,575,175,575,175,575,175,575,200,575,675,100,200,575,200,575,200,575,200,575,200,575,200,575,650,100,200,100,4625,2375,650,100,650,100,650,100,675,100,650,100,675,100,650,100,650,100,650,100,650,100,650,100,650,125,650,125,650,125,650,125,650,125,650,125,650,125,650,125,175,600,175,600,175,575,175,575,175,575,175,575,175,575,175,575,175,575,175,575,175,575,175,575,175,600,175,575,175,575,175,575,175,575,175,575,175,575,175,575,175,600,650,125,175,575,175,575,175,575,175,575,175,575,175,575,650,125,175,125};
|
||||
//PROGMEM int temp[]={725,150,600,150,600,150,600,150,600,650,125,150,600,175,600,175,600,175,600,175,600,175,600,650,125,175,125,4650,2375,650,125,650,125,650,125,650,125,650,125,650,125,650,125,650,125,650,125,650,125,650,125,650,125,650,125,650,125,650,125,650,125,650,125,650,125,650,125,650,125,650,125,175,600,175,600,650,125,175,600,175,600,175,600,175,600,175,600,175,600,175,600,175,600,175,600,175,600,175,600,175,575,175,575,175,575,175,575,175,600,650,125,175,575,175,575,175,575,175,575,175,575,175,600,650,125,175,100,4625,2375,300,325};
|
||||
//PROGMEM int temp[]={550,300,475,300,475,325,950,800,450,325,925,825,925,325,450,350,425,350,425,350,425,825,425,350,900,850,900,850,900,850,875,850,425,375,400,375,400,375,400,375,400,375,400,375,400,375,875,375,400,350,1325,875,400,375,400,375,400,375,875,875,400,400,875,875,875,400,400,400,400,400,400,400,375,875,400,375,875,875,875,875,875,875,875,875,400,375,400,375,400,375,400,375,400,375,400,375,400,375,875,375,400,350,1325,875,400,375,400,375,400,375,875,875,400,375,875,875,875,400,400,400,400,400,400,400,400,875,400,375,875,875,875,875,875,875,875,875,400,375,400,375,400,375,400,375,400,375,400,375,400,375,875,375,400,0,0,0,0,0,0,0,0,0,0,0,0,0};
|
||||
//PROGMEM int temp[]={625,300,575,275,550,300,1025,875,500,350,1000,925,1000,400,475,400,450,400,450,375,450,900,475,375,1000,925,975,925,975,925,950,925,450,400,450,400,450,400,450,400,450,400,450,400,450,400,950,425,425,375,1450,950,425,425,425,425,425,425,950,950,425,425,950,975,950,425,425,425,425,425,425,425,425,950,425,425,950,950,950,950,950,950,950,950,425,425,425,425,425,425,425,425,425,425,425,425,425,425,950,425,425,375,1450,950,425,425,425,425,425,425,950,950,425,425,950,975,950,425,425,425,425,425,425,425,425,950,425,425,950,950,950,950,950,950,950,950,450,425,425,425,425,425,425,425,425,425,425,425,425,425,950,425,425};
|
||||
//PROGMEM int temp[]={325,825,875,225,225,875,850,225,225,875,225,875,225,875,225,850,225,875,225,875,225,850,225,850,225,875,825,250,225,875,850,225,225,875,825,250,200,900,825,275,200,900,200,900,200,900,825,250,200};
|
||||
//pir PROGMEM int temp[]={475,925,400,950,1150,175,400,950,375,950,1125,200,1100,225,1100,250,1075,250,1075,275,1050,275,1050,275,1050,275,1050,275,275,1050,1050,275,300,1050,1050,275,300,1050,300,1050,1050,275,300,1050,275,1050,1050,275,275};
|
||||
//homeconfort PROGMEM int temp[]={2675,200,600,200,600,700,100,700,100,200,600,700,100,700,100,200,600,700,100,225,600,725,75,225,600,225,575,725,75,225,575,225,575,225,575,725,75,725,75,725,75,725,75,225,575,725,75,225,575,225,575,225,575,225,575,225,575,250,575,250,575,250,575,250,575,250,550,250,550,250,550,250,550,250,550,250,550,250,550,250,575,725,75,250,550,250,550,250,550,250,550,250,550,250,550,750,50,250,50};
|
||||
//eurodomest //20;03;DEBUG;Pulses=50;Pulses(uSec)= PROGMEM int temp[]={275,800,200,800,200,800,175,800,775,225,175,800,200,800,200,800,200,800,775,225,175,800,175,800,775,225,775,225,200,800,775,225,200,800,775,225,200,800,200,800,775,225,775,225,775,225,775,225,175};
|
||||
//lacrosse hum PROGMEM int temp[]={1400,1300,1325,1300,1325,1275,1350,1150,225,1300,1325,1275,1325,1275,225,1300,1325,1275,225,1275,1350,1275,225,1300,1325,1275,225,1300,225,1275,1350,1275,1350,1275,250,1275,225,1275,1350,1275,1350,1300,225,1300,1350,1275,225,1275,225,1275,225,1275,225,1275,1325,1275,225,1300,1325,1275,1325,1275,1325,1275,250,1275,1350,1275,1325,1300,1325,1275,250,1275,1350,1275,1325,1275,250,1275,1325,1275,250,1275,225,1275,225,1275,1350,1275,225,1275,250,1275,225,1275,1325,1275,250,1275,1350,1300,1325};
|
||||
//lacrosse temp
|
||||
//PROGMEM int temp[]={1400,1275,1350,1275,1350,1275,1325,1150,225,1275,1350,1275,1325,1275,225,1300,1325,1275,225,1300,1325,1275,1325,1275,1350,1275,225,1300,225,1275,1350,1275,1350,1300,225,1300,225,1275,1350,1275,1325,1275,250,1275,1350,1275,250,1275,225,1275,225,1275,225,1275,1325,1275,1350,1275,250,1275,1325,1275,1350,1275,1350,1275,225,1275,225,1275,1350,1275,225,1300,1325,1275,1325,1275,1350,1275,250,1275,1325,1275,250,1275,250,1275,225,1275,1350,1275,1350,1275,225,1275,1350,1275,1350,1275,225,1275,1325};
|
||||
//lacrosse wind
|
||||
//PROGMEM int temp[]={1400,1275,1350,1275,1350,1275,1325,1150,250,1275,1350,1275,1325,1275,250,1275,1325,1275,1350,1275,225,1275,225,1275,1350,1300,225,1275,225,1275,1350,1275,1325,1275,225,1275,225,1275,1325,1275,1325,1275,250,1275,1350,1300,225,1275,225,1275,225,1275,225,1275,1350,1275,1325,1275,1350,1275,1325,1275,1350,1275,1325,1275,1350,1275,1325,1300,1325,1275,225,1275,225,1275,1350,1275,225,1275,225,1300,225,1275,250,1275,225,1275,225,1275,250,1275,225,1275,225,1275,1350,1275,250,1275,225,1275,1325};
|
||||
//powerfix 2 off
|
||||
//PROGMEM int temp[]={600,600,1250,625,1225,625,1225,625,1250,1300,550,625,1225,625,1225,625,1250,625,1225,625,1225,625,1225,625,1250,1300,575,625,1225,625,1225,625,1250,625,1225,650,1225,1300,550,625,1175};
|
||||
//PROGMEM int temp[]={600,600,1250,600,1250,625,1225,625,1225,1275,575,625,1225,625,1225,625,1250,625,1225,650,1200,625,1225,625,1225,1300,550,1300,575,1300,550,1300,575,650,1225,625,1225,625,1225,625,1175};
|
||||
//PROGMEM int temp[]={3675,950,250,950,250,950,950,250,250,950,250,950,250,950,950,275,250,950,950,275,250,950,950,250,250,950,950,250,250,950,250,950,250,950,950,250,250,950,950,250,250,950,950,275,250,950,950,275,250};
|
||||
// mising bit 102 pulses //PROGMEM int temp[]={1400,1275,1325,1275,1325,1275,1325,1175,225,1300,1350,1275,1350,1275,225,1300,1325,1300,1325,1275,1325,1300,225,1300,1325,1275,225,1275,225,1300,1325,1275,1325,1275,250,1275,225,1275,1325,1275,1350,1275,225,1275,1325,1275,225,1225,300,1275,250,1275,225,1275,1325,1275,1325,1300,225,1275,225,1275,1325,1300,1325,1275,225,1275,225,1275,225,1275,225,1275,1325,1275,1325,1275,250,1275,250,1275,1325,1275,1350,1275,225,1275,225,1300,1325,1275,1350,1275,1325,1300,1325,1275,1350,1275,1325};
|
||||
//lacrosse v3
|
||||
//PROGMEM int temp[]={825,275,750,275,750,300,750,300,750,300,750,275,750,275,750,300,750,300,750,300,250,800,725,300,750,300,250,800,725,300,225,800,225,800,250,800,250,800,725,300,250,800,725,300,750,300,725,300,250,800,250,800,225,800,750,300,250,800,725,300,250,800,725,300,250,800,725,300,725,300,250,800,725,300,725,300,250,800,725,300,250,800,725,300,725,300,725,300,725,300,250,800,225,800,225,800,725,300,725,300,225,800,225,800,725,300,725,300,725,300,250,800,250,800,725,300,725,300,725,300,250,800,725,300,725,300,725,300,225,800,225,800,225,800,725,300,225,800,225,800,250,800,725,300,225,800,225,800,225,800,250,800,250,800,225,800,725,300,225,800,225,600};
|
||||
// oregon v1
|
||||
//PROGMEM int temp[]={1525,1025,1475,1050,1450,2350,1475,1025,2800,1025,1450,2375,1450,1050,2800,2375,1450,1050,1450,1050,1450,1050,1450,1050,2800,1050,1450,2350,1475,1025,1475,1050,1450,1050,1450,1050,1425,1050,1450,1050,1450,1050,2800,2375,2800,2375,2800,1050,1450,1075,1425};
|
||||
//PROGMEM int temp[]={1725,1100,1650,1100,1650,1100,1650,1100,1650,1100,1650,1100,1625,1125,1625,1125,1625,1125,1625,1100,1625,1100,1625,4150,5675,225,3100,1125,1625,1125,1625,2600,3100,2600,1625,1125,3100,2600,1625,1125,3075,1125,1625,2600,3100,2600,1625,1125,3075,2600,1625,1125,1625,1125,1625,1125,1625,1125,1600,1125,3075,2600,1600,1125,3075,2600,1625,1125,1600,1150,3075,600};
|
||||
//20;38;DEBUG;Pulses=66;Pulses(uSec)= v1
|
||||
//PROGMEM int temp[]={1725,1075,1675,1075,1675,1075,1675,1075,1675,1050,1700,1050,1675,4125,5725,5075,1650,2575,3125,1100,1625,2575,1600,1150,3175,2500,1700,1050,1625,1150,3125,2550,3150,1075,1650,2550,1650,1100,1575,1175,3100,2575,1625,1125,1650,1075,1675,1075,1650,1125,1575,1175,3100,1100,1600,2600,1625,1125,1650,1100,1625,1125,1575,1175,3100,600};
|
||||
//20;04;DEBUG;Pulses=50;Pulses(uSec)=
|
||||
//PROGMEM int temp[]={300,1020,240,1020,240,1020,240,1020,240,1020,240,1020,240,1020,990,300,240,1020,240,1020,240,1020,240,1020,240,1020,990,270,240,1020,990,300,240,1020,240,1020,240,1020,990,300,240,1020,990,300,240,1020,990,300,240,6990};
|
||||
// chuango
|
||||
//PROGMEM int temp[]={1625,425,1550,450,1575,400,525,1450,1575,425,1550,425,475,1550,1450,525,1450,550,375,1525,475,1475,500,1475,1575,400,525,1450,1550,425,1525,500,1475,575,350,1600,400,1550,475,1500,500,1475,1550,425,1550,425,1550,425,450};
|
||||
//PROGMEM int temp[]={1975,275,900,250,225,975,250,975,250,975,225,975,900,250,900,250,900,250,250,950,225,975,900,250,225,950,225,975,250,950,225,975,900,250,900,250,900,250,250,950,900,250,250,950,225,950,925,250,250};
|
||||
//Imagintronix:
|
||||
//PROGMEM int temp[]={390,870,420,870,420,870,420,870,420,870,420,870,420,870,420,870,1260,870,420,870,1260,870,420,870,1230,870,420,870,1260,870,420,870,1260,870,1260,870,1260,870,1230,870,1260,870,420,870,1260,870,420,870,1260,870,420,870,1260,870,1260,870,1260,870,420,870,1260,870,420,870,420,870,420,870,420,870,420,870,420,870,420,870,420,870,420,870,420,870,1230,870,1260,870,420,870,420,870,420,840,420,840,1260,6990};
|
||||
|
||||
//20;10;DEBUG;Pulses=42;Pulses(uSec)=Chacon:
|
||||
//PROGMEM int temp[]={630,570,1230,540,1230,540,1230,540,1230,570,1230,540,1230,540,1230,540,1230,570,1230,540,1230,540,1230,540,1230,570,1200,540,1200,570,1170,1230,540,570,1200,540,1200,540,1170,1230,540,6990};
|
||||
//PROGMEM int temp[]={660,510,1260,510,1260,510,1260,510,1260,540,1260,510,1260,540,1260,540,1230,540,1230,540,1230,540,1230,540,1230,570,1230,540,1230,540,1230,540,1230,570,1230,540,1230,540,1230,540,1230,6990};
|
||||
//PROGMEM int temp[]={120,510,90,510,510,90,510,90,120,510,90,510,510,90,510,90,510,90,90,510,120,510,120,510,510,90,510,90,90,510,510,90,510,90,90,510,90,510,120,510,120,510,120,510,510,90,510,90,120,6240,120};
|
||||
//PROGMEM int temp[]={90,510,510,90,510,90,120,510,510,90,90,510,90,510,510,90,510,90,510,90,120,510,510,90,120,510,510,90,510,90,90,510,90,510,510,90,510,90,510,90,90,510,90,510,510,90,510,90,90,6300,90};
|
||||
//PROGMEM int temp[]={330,360,270,360,270,330,270,360,270,360,270,360,270,330,270,360,270,360,270,360,270,360,270,3960,660,360,270,780,690,360,690,360,660,360,270,780,270,780,270,780,690,360,270,780,270,780,690,360,270,780,660,360,270,780,270,780,690,360,270,780,660,360,270,780,660,360,270,780,660,360,270,780,270,780,690,360,690,360,660,360,270,780,660,360,690,360,660,360,660,360,660,360,270,780,690,360,660,360,660,360,270,780,660,360,270,780,270,780,270,780,690,360,270,780,690,360,690,360,270,780,660,360,690,360,690,360,270,780,660,360,660,360,690,360,690,360,270,780,270,780,660,360,660,360,660,360,270,780,690,360,660,390,660,360,270,6990};
|
||||
// bofu
|
||||
//PROGMEM int temp[]={1200,2370,1560,180,600,210,600,210,600,210,210,600,210,600,600,210,600,210,210,600,600,210,210,600,600,210,600,210,600,180,600,180,600,180,210,600,600,180,600,180,210,600,210,600,180,600,180,600,600,180,600,210,180,600,180,600,180,600,180,600,210,600,210,600,600,180,600,210,210,600,600,210,210,600,600,210,600,210,210,600,210,600,600,180,600};
|
||||
//PROGMEM int temp[]={270,600,210,600,210,600,180,600,180,600,180,630,180,600,180,630,180,600,180,600,180,600,180,600,180,6990};
|
||||
//Alecto
|
||||
//PROGMEM int temp[]={1800,2010,1710,2010,3690,3960,1710,2010,1710,2010,1710,2010,1710,3960,1710,3960,1710,3960,1710,2010,1710,3960,1740,2010,1710,2010,1710,3960,1710,2010,1710,2010,1710,3960,1710,2010,1710,2010,1710,3960,1740,3960,1710,2010,1710,2010,1710,2010,1710,2010,1710,3960,1710,2010,1710,3960,1710,2010,1710,2010,1710,2010,1710,1980,1710,3960,1710,2010,1710,3960,1710,3960,1710,3960,1710,3960,1710,2010,1710,2010,1710,2010,1710,3960,1710,2010,1710,3960,1710,3960,1710,2010,1710,3960,1710,3960,1710,2010,1710,3960,1710,3960,1710,2010,1710,2010,1710,3960,1710,3960,1710,3960,1710,3960,1740,2010,1710,3960,1740,2010,1710,3960,1710,3960,1710,3960,1710,3960,1710,1980,1740,3960,1710,3960,1740,1980,1740,1980,1710,3960,1710,2010,1710,2010,1740,2010,1710,3960,1710,6990};
|
||||
//PROGMEM int temp[]={360,150,600,180,600,510,300,510,300,510,300,510,300,510,300,210,600,210,630,510,300,210,600,540,300,510,300,210,600,210,600,510,300,180,600,510,300,510,300,210,600,540,300,210,600,510,300,210,600,210,600,540,300,510,270,210,600,6990};
|
||||
//PROGMEM int temp[]={1200,2370,1530,180,600,210,600,210,600,210,210,600,210,600,600,210,600,210,210,600,600,210,210,600,600,210,600,180,600,180,600,180,600,180,210,600,600,180,600,180,210,600,180,600,180,600,180,600,600,210,600,210,180,600,180,600,180,600,210,600,210,600,210,600,600,210,600,210,210,600,600,210,210,600,600,210,600,210,210,600,210,600,600,180,600,6990};
|
||||
// perel
|
||||
//PROGMEM int temp[]={420,900,1080,180,360,900,360,900,360,900,1080,180,360,900,1080,210,330,930,1080,210,330,930,330,930,360,930,330,930,330,930,330,930,330,930,330,930,330,930,1080,210,330,930,1080,210,330,930,1080,210,330,6990};
|
||||
// Europe
|
||||
//PROGMEM int temp[]={1290,3240,450,3240,450,3240,1230,3240,1230,3240,450,3240,1230,3240,1230,3240,1230,3240,1230,3240,1230,3240,1230,3240,1230,3240,1230,3240,450,3240,1230,3240,1230,3240,1230,3240,1230,3240,1230,3240,1230,3240,1200,3240,1230,3240,1200,3240,1230,3240,450,6990};
|
||||
//kaku doorbell
|
||||
//PROGMEM int temp[]={300,950,250,950,250,950,950,275,250,950,250,950,250,950,950,275,250,950,950,275,250,950,950,250,250,950,950,275,250,950,250,950,250,950,950,275,250,950,950,250,250,950,950,275,250,950,950,250,250};
|
||||
//rev tristate
|
||||
//PROGMEM int temp[]={330,960,930,270,240,960,930,270,930,270,930,270,240,960,930,270,930,270,930,270,240,960,930,270,240,960,930,270,240,960,240,960,240,930,240,960,240,960,240,960,240,960,240,960,930,270,930,270,240,6990};
|
||||
//PROGMEM int temp[]={270,990,930,270,210,960,930,270,930,270,930,270,210,960,900,270,210,960,900,270,900,270,900,270,210,960,900,270,210,960,210,960,210,960,210,960,210,960,210,960,900,270,900,270,210,960,210,960,210,6990};
|
||||
// lidl 3state
|
||||
//PROGMEM int temp[]={180,930,900,270,210,930,210,930,210,930,210,930,210,930,210,930,210,930,210,930,210,930,210,930,210,930,210,930,210,930,210,930,210,930,870,270,210,930,870,270,210,930,210,930,870,270,900,270,210,6990};
|
||||
// impuls
|
||||
//PROGMEM int temp[]={60,330,360,30,60,330,360,30,60,330,360,30,60,330,360,30,360,30,360,30,60,330,60,330,60,330,60,330,60,330,60,330,60,330,60,330,60,330,60,330,60,330,360,30,60,330,60,330,60,6990;};
|
||||
//biowin
|
||||
//PROGMEM int temp[]={1200,1860,480,1860,480,3780,480,3780,480,3780,480,3780,480,3780,480,3780,480,3810,480,1890,480,3780,480,1860,450,1860,480,3750,480,3780,480,3780,480,1890,480,1860,480,1860,480,1860,480,1860,480,1860,480,3750,480,1890,480,3780,480,1860,480,1860,480,3750,480,1860,480,1860,480,1860,480,3750,480,1890,450,1860,480,1860,480,3750,480,1860,480,3780,480,3780,480,1860,480,1890,480,6990};
|
||||
//somfy up 88
|
||||
//PROGMEM int temp[]={1200,2490,2400,2490,4710,1200,1170,1200,1170,1200,1170,1200,540,570,510,570,1170,570,510,570,510,540,540,1200,1170,1200,540,570,1170,570,540,570,510,540,540,570,510,570,540,1200,1170,1200,1170,570,510,1200,1170,570,540,1200,540,570,1170,1200,1170,1200,510,540,540,570,1170,570,540,570,510,1200,540,540,540,570,1170,570,540,1200,1170,540,540,570,540,1200,1170,570,510,570,540,1200,510,6990};
|
||||
//somfy down? 84
|
||||
//PROGMEM int temp[]={3540,1140,1110,1140,1110,1140,1140,1200,1170,1200,1170,570,540,570,540,1200,1170,1200,1170,1200,1170,570,510,570,540,1200,510,570,540,570,1170,570,540,1200,1170,570,510,1200,1170,570,540,1200,510,570,1170,1200,1170,1200,510,540,540,540,1170,570,540,570,540,1200,540,540,510,570,1170,570,510,1200,1170,540,540,570,540,1200,1170,540,540,570,540,1200,510,6990};
|
||||
// somfy my 80
|
||||
//PROGMEM int temp[]={1200,2490,2400,2490,4710,1200,1170,1200,1170,1200,510,540,1170,1200,540,540,1170,1200,540,540,1170,1200,1170,540,540,1200,1170,1200,510,540,1170,540,540,570,540,540,540,570,540,1200,510,570,510,540,540,540,1170,1200,1170,1200,1170,540,540,1200,510,570,510,570,1170,1200,1170,570,510,570,540,540,540,1200,1170,1200,1170,570,540,570,540,1200,1170,570,540,570,540,1200,1170,6990};
|
||||
//PROGMEM int temp[]={270,930,210,930,210,930,870,270,180,930,870,270,180,930,870,270,180,930,840,270,180,930,210,930,210,930,870,270,180,930,870,270,180,930,870,270,180,930,870,270,210,930,180,930,180,930,840,270,180,6990};
|
||||
//Xiron
|
||||
//PROGMEM int temp[]={990,870,900,870,870,390,390,390,390,870,390,390,870,390,390,900,390,390,390,390,870,390,390,390,390,870,390,390,870,390,390,870,390,390,390,390,900,870,390,390,870,870,870,870,870,390,390,870,870,870,390,390,870,870,390,390,870,390,390,390,390,870,390,390,870,390,390,390,390,390,390,390,390,390,390,870,870,870,870,870,870,390,390,390,390,870,870,390,390,870,390,390,870,870,390,390,870,900,390,390,390,390,390,390,30,6990};
|
||||
//if (RawSignal.Number==66){
|
||||
// for (i=0;i<160;i++) {
|
||||
// //RawSignal.Pulses[1+i]=temp[i]/25;
|
||||
// RawSignal.Pulses[1+i]=temp[i]/RawSignal.Multiply;
|
||||
// }
|
||||
// RawSignal.Number=106;
|
||||
//}
|
||||
// -
|
||||
//if (RawSignal.Number==66){
|
||||
//Serial.print("20;01;LaCrosseV2;ID=0606;"); // Label
|
||||
// ----------------------------------
|
||||
//int sensordata=0x0e; // 9=203 10=225
|
||||
//sprintf(pbuffer, "WINDIR=%04d;", sensordata);
|
||||
//Serial.print( pbuffer );
|
||||
//sensordata=6;
|
||||
//sensordata=sensordata*36;
|
||||
//sprintf(pbuffer, "WINGS=%04x;", sensordata);
|
||||
//Serial.print( pbuffer );
|
||||
//sprintf(pbuffer, "WINSP=%04x;", sensordata);
|
||||
//Serial.println( pbuffer );
|
||||
//}
|
||||
// ==========================================================================
|
||||
// Kill ALL Short RF packets
|
||||
// ==========================================================================
|
||||
if (RawSignal.Number < 24) { // Less than 24 pulses?
|
||||
RawSignal.Number=0; // Kill packet
|
||||
return true; // abort processing
|
||||
}
|
||||
// ==========================================================================
|
||||
// DEBUG
|
||||
// ==========================================================================
|
||||
if (RFDebug==true) {
|
||||
// ----------------------------------
|
||||
// Output
|
||||
// ----------------------------------
|
||||
sprintf(pbuffer, "20;%02X;", PKSequenceNumber++); // Node and packet number
|
||||
Serial.print( pbuffer );
|
||||
// ----------------------------------
|
||||
Serial.print(F("DEBUG;Pulses=")); // debug data
|
||||
Serial.print(RawSignal.Number);
|
||||
Serial.print(F(";Pulses(uSec)="));
|
||||
//for(i=1;i<RawSignal.Number;i++) {
|
||||
for(i=1;i<RawSignal.Number+1;i++) {
|
||||
Serial.print(RawSignal.Pulses[i]*RawSignal.Multiply);
|
||||
//if (i < RawSignal.Number-1) Serial.write(',');
|
||||
if (i < RawSignal.Number) Serial.write(',');
|
||||
}
|
||||
Serial.println(";");
|
||||
}
|
||||
// ==========================================================================
|
||||
// Beginning of Signal translation for Impuls
|
||||
// ==========================================================================
|
||||
// 20;D7;DEBUG;Pulses=250;Pulses(uSec)=275,325,375,25,75,350,375,25,75,350,375,25,75,350,375,25,75,350,375,25,75,325,375,25,75,325,375,25,75,350,375,25,75,350,375,25,75,350,375,25,75,325,75,350,75,325,375,25,75,4700,75,325,375,25,75,325,375,25,75,350,375,25,75,350,375,25,75,350,375,25,75,325,375,25,75,325,375,25,75,350,375,25,75,350,375,25,75,350,375,25,75,350,75,350,75,325,375,25,75,4700,75,325,375,25,75,325,375,25,75,350,375,25,75,350,375,25,75,350,375,25,75,325,375,25,75,325,375,25,75,325,375,25,75,350,375,25,75,350,375,25,75,350,75,350,75,325,375,25,75,4700,75,325,375,25,75,325,375,25,75,325,375,25,75,350,375,25,75,350,375,25,75,350,375,25,75,325,375,25,75,325,375,25,75,350,375,25,75,350,375,25,75,350,75,325,75,350,375,25,75,4700,75,350,375,25,75,325,375,25,75,325,375,25,75,350,375,25,75,350,375,25,75,350,375,25,75,325,375,25,75,325,375,25,75,325,375,25,75,350,375,25,75,350,75,325,75,350,375,25,75;
|
||||
if ((RawSignal.Number == 250) || (RawSignal.Number == RAW_BUFFER_SIZE-1) ) { // Impuls
|
||||
if (RawSignal.Pulses[50] > PULSE4200) {
|
||||
if (RawSignal.Pulses[100] > PULSE4200) {
|
||||
if (RawSignal.Pulses[150] > PULSE4200) {
|
||||
RawSignal.Number=50; // New packet length
|
||||
RawSignal.Pulses[0]=33; // signal the plugin number that should process this packet
|
||||
return false; // packet detected, conversion done
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
// ==========================================================================
|
||||
// End of Signal translation
|
||||
// ==========================================================================
|
||||
// ==========================================================================
|
||||
// Beginning of Signal translation for Home Confort Switches/Remotes
|
||||
// ==========================================================================
|
||||
if (RawSignal.Number == 200) {
|
||||
if (RawSignal.Pulses[1] > PULSE2000) {
|
||||
if (RawSignal.Pulses[100] > PULSE4000) {
|
||||
if (RawSignal.Pulses[101] > PULSE2000) {
|
||||
RawSignal.Number=100; // New packet length
|
||||
RawSignal.Pulses[0]=11; // signal the plugin number that should process this packet
|
||||
return false; // packet detected, conversion done
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
// ==========================================================================
|
||||
// End of Signal translation
|
||||
// ==========================================================================
|
||||
// ==========================================================================
|
||||
// Beginning of Signal translation for Intertek Unitec Switches/Remotes
|
||||
// ==========================================================================
|
||||
if (RawSignal.Number == 202) {
|
||||
if (RawSignal.Pulses[2] > PULSE2000) {
|
||||
if (RawSignal.Pulses[52] > PULSE2000) {
|
||||
if (RawSignal.Pulses[102] > PULSE2000) {
|
||||
if (RawSignal.Pulses[1] < PULSE500) {
|
||||
RawSignal.Number=50; // New packet length
|
||||
RawSignal.Pulses[0]=19; // signal the plugin number that should process this packet
|
||||
return false; // packet detected, conversion done
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
// ==========================================================================
|
||||
// End of Signal translation
|
||||
// ==========================================================================
|
||||
// ==========================================================================
|
||||
// Beginning of Signal translation for HomeEasy HE844 mode 4 - compatibility mode
|
||||
// ==========================================================================
|
||||
//if (RawSignal.Number == 234) {
|
||||
// if (HEconversiontype==0) { // Reject the entire packet
|
||||
// if ((RawSignal.Pulses[2] > PULSE4000) && (RawSignal.Pulses[2+58] > PULSE4000) && (RawSignal.Pulses[2+58+58] > PULSE4000) ){
|
||||
// RawSignal.Pulses[0]=15; // Instruct plugin 3 to skip any packets it might see after this
|
||||
// RawSignal.Number=0; // Kill packet
|
||||
// return true; // abort processing
|
||||
// }
|
||||
// }
|
||||
//}
|
||||
// ==========================================================================
|
||||
// End of Signal translation HomeEasy HE842
|
||||
// ==========================================================================
|
||||
|
||||
// ==========================================================================
|
||||
// END plugin 001 if the incoming packet is not oversized and resume normal processing of plugins
|
||||
// there is no need to do all the checks if there never will be a match
|
||||
if (RawSignal.Number < OVERSIZED_LIMIT) return false;
|
||||
// ==========================================================================
|
||||
// ##########################################################################
|
||||
// ==========================================================================
|
||||
// Beginning of Signal translation for oversized packets (more pulses than handled by any plugin)
|
||||
// ==========================================================================
|
||||
|
||||
// ==========================================================================
|
||||
// Beginning of Signal translation for Flamingo FA500R
|
||||
// ==========================================================================
|
||||
if (RawSignal.Number > 330 && RawSignal.Number < 378) {
|
||||
int pos1=RawSignal.Number - 130;
|
||||
int pos2=RawSignal.Number - 130 - 58;
|
||||
if (RawSignal.Pulses[pos1] > PULSE2000 && RawSignal.Pulses[pos2] > PULSE4000) {
|
||||
for (i=0;i<58;i++){
|
||||
RawSignal.Pulses[1+i]=RawSignal.Pulses[pos2+1+i];
|
||||
}
|
||||
RawSignal.Pulses[0]=12; // Data will be processed by plugin 12
|
||||
RawSignal.Number=58; // New packet length
|
||||
return false; // Conversion done, stop plugin 1 and continue with regular plugins
|
||||
}
|
||||
}
|
||||
// ==========================================================================
|
||||
// End of Signal Translation
|
||||
// ==========================================================================
|
||||
// ==========================================================================
|
||||
// Beginning of Signal translation for Conrad RSL
|
||||
// ==========================================================================
|
||||
//Conrad RSL
|
||||
//20;87;DEBUG;Pulses=462;Pulses(uSec)=1260,420,510,1140,1230,420,1230,420,510,1140,1230,420,1230,420,510,1140,510,1140,510,1140,510,1140,510,1140,510,1140,510,1140,510,1140,510,1140,510,1140,510,1140,510,1140,510,1140,1230,420,1230,420,1230,420,1230,420,1230,420,510,1140,1230,420,510,1140,510,1140,510,1140,510,1140,510,1140,510,6930,1230,420,510,1140,1230,420,1230,420,510,1140,1230,420,1230,420,510,1140,510,1140,510,1140,510,1140,510,1140,510,1140,510,1140,510,1140,510,1140,510,1140,510,1140,510,1140,510,1140,1230,420,1230,420,1230,420,1230,420,1230,420,510,1140,1230,420,510,1140,510,1140,510,1140,510,1140,510,1140,510,6930,1230,420,510,1140,1230,420,1230,420,510,1140,1230,420,1230,420,510,1140,510,1140,510,1140,510,1140,510,1140,510,1140,510,1140,510,1140,510,1140,510,1140,510,1140,510,1140,510,1140,1230,420,1230,420,1230,420,1230,420,1230,420,510,1140,1230,420,510,1140,510,1140,510,1140,510,1140,510,1140,510,6930,1230,420,510,1140,1230,420,1230,420,510,1140,1230,420,1230,420,510,1140,510,1140,510,1140,510,1140,510,1140,510,1140,510,1140,510,1140,510,1140,510,1140,510,1140,510,1140,510,1140,1230,420,1230,420,1230,420,1230,420,1230,420,510,1140,1230,420,510,1140,510,1140,510,1140,510,1140,510,1140,510,6930,1230,420,510,1140,1230,420,1230,420,510,1140,1230,420,1230,420,510,1140,510,1140,510,1140,510,1140,510,1140,510,1140,510,1140,510,1140,510,1140,510,1140,510,1140,510,1140,510,1140,1230,420,1230,420,1230,420,1230,420,1230,420,510,1140,1230,420,510,1140,510,1140,510,1140,510,1140,510,1140,510,6930,1230,420,510,1140,1230,420,1230,420,510,1140,1230,420,1230,420,510,1140,510,1140,510,1140,510,1140,510,1140,510,1140,510,1140,510,1140,510,1140,510,1140,510,1140,510,1140,510,1140,1230,420,1230,420,1230,420,1230,420,1230,420,510,1140,1230,420,510,1140,510,1140,510,1140,510,1140,510,1140,510,6930,1230,420,510,1140,1230,420,1230,420,510,1140,1230,420,1230,420,510,1140,510,1140,510,1140,510,1140,510,1140,510,1140,510,1140,510,1140,510,1140,510,1140,510,1140,510,1140,510,1140,1230,420,1230,420,1230,420,1230,420,1230,420,510,1140,1230,420,510,1140,510,1140,510,1140,510,1140,510,1140,510,6990;
|
||||
if (RawSignal.Number == 462) {
|
||||
if ( (RawSignal.Pulses[66] > PULSE6500) && (RawSignal.Pulses[66+66] > PULSE6500) && (RawSignal.Pulses[66+66+66] > PULSE6500) ) {
|
||||
RawSignal.Number=66; // New packet length
|
||||
return false; // Conversion done, terminate plugin 1 and continue with regular plugins
|
||||
}
|
||||
}
|
||||
// ==========================================================================
|
||||
// End of Signal Translation
|
||||
// ==========================================================================
|
||||
// ==========================================================================
|
||||
// Beginning of Signal translation for HomeEasy HE842/HE852/HE863
|
||||
// ==========================================================================
|
||||
if (RawSignal.Number > 460) { // && RawSignal.Number < 470) {
|
||||
if (HEconversiontype==0) { // Reject the entire packet
|
||||
if ((RawSignal.Pulses[2] > PULSE4000) && (RawSignal.Pulses[2+58] > PULSE4000) && (RawSignal.Pulses[2+58+58] > PULSE4000) ){
|
||||
RawSignal.Pulses[0]=15; // Instruct plugin 3 to skip any packets it might see after this
|
||||
RawSignal.Number=0; // Kill packet
|
||||
return true; // abort processing
|
||||
}
|
||||
} else { // Convert to Elro Method 1 (same as FA500 Method 1)
|
||||
int pos1=RawSignal.Number - 58;
|
||||
//if (RawSignal.Pulses[pos1]*RawSignal.Multiply > 4000) {
|
||||
if (RawSignal.Pulses[pos1] > PULSE4000) {
|
||||
for (i=0;i<58;i++){
|
||||
RawSignal.Pulses[1+i]=RawSignal.Pulses[pos1+1+i];
|
||||
}
|
||||
RawSignal.Number=58; // New packet length
|
||||
return false; // Conversion done, stop plugin 1 and continue with regular plugins
|
||||
}
|
||||
}
|
||||
}
|
||||
// ==========================================================================
|
||||
// End of Signal translation HomeEasy HE842
|
||||
// ==========================================================================
|
||||
|
||||
// **************************************************************************
|
||||
// Full buffer size checks, >>>>>> STATIC checks <<<<<
|
||||
// **************************************************************************
|
||||
|
||||
// ==========================================================================
|
||||
// Beginning of Signal translation for Forrinx
|
||||
// ==========================================================================
|
||||
if (RawSignal.Number == RAW_BUFFER_SIZE-1) {
|
||||
if ((RawSignal.Pulses[2] > PULSE6000) && (RawSignal.Pulses[2+50] > PULSE6000) && (RawSignal.Pulses[2+50+50] > PULSE6000)) {
|
||||
for (i=0;i<50;i++){
|
||||
RawSignal.Pulses[1+i]=RawSignal.Pulses[3+i]; // reorder pulse array
|
||||
}
|
||||
RawSignal.Number=51; // New packet length (report 51 and not 50 to avoid handling by other plugins
|
||||
RawSignal.Pulses[0]=76; // signal the plugin number that should process this packet
|
||||
return false; // packet detected, conversion done
|
||||
}
|
||||
}
|
||||
// ==========================================================================
|
||||
// ==========================================================================
|
||||
// Beginning of Signal translation for bofu
|
||||
// ==========================================================================
|
||||
if (RawSignal.Number == RAW_BUFFER_SIZE-1) {
|
||||
if ( (RawSignal.Pulses[1] > PULSE4200) && (RawSignal.Pulses[2] > PULSE2000) && (RawSignal.Pulses[3] > PULSE1100) ) {
|
||||
if ( (RawSignal.Pulses[1+86] > PULSE4200) && (RawSignal.Pulses[2+86] > PULSE2000) && (RawSignal.Pulses[3+86] > PULSE1100) ) {
|
||||
RawSignal.Number=85; // New packet length
|
||||
return false; // Conversion done, stop plugin 1 and continue with regular plugins
|
||||
}
|
||||
}
|
||||
}
|
||||
// ==========================================================================
|
||||
|
||||
// **************************************************************************
|
||||
// Full buffer size checks, >>>> SCANNING checks <<<<< sorted by packet size
|
||||
// **************************************************************************
|
||||
|
||||
// ==========================================================================
|
||||
// Beginning of Signal translation for Silvercrest Doorbell
|
||||
// ==========================================================================
|
||||
if (RawSignal.Number == RAW_BUFFER_SIZE-1) {
|
||||
for (j=2;j<114;j++) { // Only check twice the total RF packet length we are looking for
|
||||
if (RawSignal.Pulses[j] > PULSE1100) { // input is going to fast skip to where new part is going to start
|
||||
if (j+114 > RAW_BUFFER_SIZE-1) break; // cant be the packet we look for
|
||||
if ( (RawSignal.Pulses[j+114] > PULSE1100) && (RawSignal.Pulses[j+114+114] > PULSE1100) && (RawSignal.Pulses[j+114+114+114] > PULSE1100) ) { // first long delay found, make sure we have another at the right position
|
||||
for (i=0;i<114;i++){
|
||||
RawSignal.Pulses[1+i]=RawSignal.Pulses[j+1+i]; // reorder pulse array
|
||||
}
|
||||
RawSignal.Number=114; // New packet length
|
||||
RawSignal.Pulses[0]=75; // signal the plugin number that should process this packet
|
||||
return false; // Conversion done, stop plugin 1 and continue with regular plugins
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
// ==========================================================================
|
||||
// ==========================================================================
|
||||
// Beginning of Signal translation for Home Confort Switches/Remotes
|
||||
// ==========================================================================
|
||||
if (RawSignal.Number > 299) { // Scan for corrupted/chained Home Confort RF packets
|
||||
if (RawSignal.Pulses[1] > PULSE2000) {
|
||||
if (RawSignal.Pulses[100] > PULSE4000) {
|
||||
if (RawSignal.Pulses[101] > PULSE2000) {
|
||||
RawSignal.Number=100; // New packet length
|
||||
RawSignal.Pulses[0]=11; // signal the plugin number that should process this packet
|
||||
return false; // packet detected, conversion done
|
||||
}
|
||||
}
|
||||
}
|
||||
for (j=1;j<104;j++) {
|
||||
//if (RawSignal.Pulses[j]*RawSignal.Multiply > 4000) {
|
||||
if (RawSignal.Pulses[j] > PULSE4000) {
|
||||
//if (RawSignal.Pulses[j+1]*RawSignal.Multiply > 2000) {
|
||||
if (RawSignal.Pulses[j+1] > PULSE2000) {
|
||||
if ( (j+98) > RawSignal.Number) break; // cant be the packet we are looking for
|
||||
//if ( (RawSignal.Pulses[j+100]*RawSignal.Multiply > 4000) && (RawSignal.Pulses[j+101]*RawSignal.Multiply > 2000) ) { // This could be a Home Confort packet
|
||||
if ( (RawSignal.Pulses[j+100] > PULSE4000) && (RawSignal.Pulses[j+101] > PULSE2000) ) { // This could be a Home Confort packet
|
||||
for (i=0;i<100;i++){
|
||||
RawSignal.Pulses[1+i]=RawSignal.Pulses[j+i]; // relocate/reorder pulse array
|
||||
}
|
||||
RawSignal.Number=100; // New packet length
|
||||
RawSignal.Pulses[0]=11; // signal the plugin number that should process this packet
|
||||
}
|
||||
return false; // Conversion done, stop plugin 1 and continue with regular plugins
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
// ==========================================================================
|
||||
// ==========================================================================
|
||||
// Beginning of Signal translation for Auriol & Xiron
|
||||
// ==========================================================================
|
||||
if (RawSignal.Number == RAW_BUFFER_SIZE-1) {
|
||||
for (int offset=0; offset < 74; offset++) {
|
||||
//if (RawSignal.Pulses[offset]*RawSignal.Multiply > 3300) {
|
||||
if (RawSignal.Pulses[offset+74] > PULSE3300
|
||||
&& RawSignal.Pulses[offset+74*2] > PULSE3300
|
||||
&& ((offset > 0 && RawSignal.Pulses[offset] > PULSE3300)
|
||||
|| RawSignal.Pulses[offset+74*3] > PULSE3300)) {
|
||||
for (i=0;i<74;i++){
|
||||
RawSignal.Pulses[1+i]=RawSignal.Pulses[offset+i+1]; // reorder pulse array
|
||||
}
|
||||
RawSignal.Number=74; // New packet length
|
||||
RawSignal.Pulses[0]=46; // signal the plugin number that should process this packet
|
||||
return false; // Conversion done, stop plugin 1 and continue with regular plugins
|
||||
}
|
||||
}
|
||||
}
|
||||
// ==========================================================================
|
||||
// ==========================================================================
|
||||
// Beginning of Signal translation for Oregon
|
||||
// ==========================================================================
|
||||
if (RawSignal.Number == RAW_BUFFER_SIZE-1) {
|
||||
for (j=50;j<104;j++) { // Only check the total RF packet length we are looking for
|
||||
//if (RawSignal.Pulses[j]*RawSignal.Multiply > 2500) { // input is going to fast skip to where new part is going to start
|
||||
if (RawSignal.Pulses[j] > PULSE1600) { // input is going to fast skip to where new part is going to start
|
||||
if (j+52 > RAW_BUFFER_SIZE-1) break; // check for overflow, cant be the packet we look for
|
||||
byte x=0;
|
||||
if ( (RawSignal.Pulses[j+52] > PULSE1600) && (RawSignal.Pulses[j+52+52] > PULSE1600) && (RawSignal.Pulses[j+52+52+52] > PULSE1600) ) x=2;
|
||||
if ( (RawSignal.Pulses[j+50] > PULSE1600) && (RawSignal.Pulses[j+50+50] > PULSE1600) && (RawSignal.Pulses[j+50+50+50] > PULSE1600) ) x=1;
|
||||
if (x !=0) {
|
||||
for (i=0;i<52;i++){
|
||||
RawSignal.Pulses[1+i]=RawSignal.Pulses[j+1+i]; // reorder pulse array
|
||||
}
|
||||
RawSignal.Number=52; // New packet length
|
||||
RawSignal.Pulses[0]=63; // signal the plugin number that should process this packet
|
||||
return false; // Conversion done, stop plugin 1 and continue with regular plugins
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
// ==========================================================================
|
||||
// ==========================================================================
|
||||
// Beginning of Signal translation for SelectPlus
|
||||
// ==========================================================================
|
||||
if (RawSignal.Number == RAW_BUFFER_SIZE-1) {
|
||||
for (j=2;j<37;j++) { // Only check the total RF packet length we are looking for
|
||||
//if (RawSignal.Pulses[j]*RawSignal.Multiply > 2500) { // input is going to fast skip to where new part is going to start
|
||||
if (RawSignal.Pulses[j] > PULSE5000) { // input is going to fast skip to where new part is going to start
|
||||
if (j+36 > RAW_BUFFER_SIZE-1) break; // cant be the packet we look for
|
||||
//if ( (RawSignal.Pulses[j+26]*RawSignal.Multiply > 2500) && (RawSignal.Pulses[j+26]*RawSignal.Multiply < 3000) && (RawSignal.Pulses[j+26+26]*RawSignal.Multiply > 2500) ) { // first long delay found, make sure we have another at the right position
|
||||
if ( (RawSignal.Pulses[j+36] > PULSE5000) && (RawSignal.Pulses[j+36+36] > PULSE5000) ) { // first long delay found, make sure we have another at the right position
|
||||
if (j != 36) {
|
||||
for (i=0;i<36;i++){
|
||||
RawSignal.Pulses[1+i]=RawSignal.Pulses[j+1+i]; // reorder pulse array
|
||||
}
|
||||
}
|
||||
RawSignal.Number=36; // New packet length
|
||||
RawSignal.Pulses[0]=70; // signal the plugin number that should process this packet
|
||||
return false; // Conversion done, stop plugin 1 and continue with regular plugins
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
// ==========================================================================
|
||||
// ==========================================================================
|
||||
// Beginning of Signal translation for Byron Doorbell
|
||||
// ==========================================================================
|
||||
if (RawSignal.Number == RAW_BUFFER_SIZE-1) {
|
||||
for (j=2;j<90 /*RawSignal.Number*/;j++) { // Only check twice the total RF packet length we are looking for
|
||||
// Byron SX
|
||||
//if (RawSignal.Pulses[j]*RawSignal.Multiply > 2500) { // input is going to fast skip to where new part is going to start
|
||||
if (RawSignal.Pulses[j] > PULSE2500) { // input is going to fast skip to where new part is going to start
|
||||
if (j+26 > RAW_BUFFER_SIZE-1) break; // cant be the packet we look for
|
||||
//if ( (RawSignal.Pulses[j+26]*RawSignal.Multiply > 2500) && (RawSignal.Pulses[j+26]*RawSignal.Multiply < 3000) && (RawSignal.Pulses[j+26+26]*RawSignal.Multiply > 2500) ) { // first long delay found, make sure we have another at the right position
|
||||
if ( (RawSignal.Pulses[j+26] > PULSE2500) && (RawSignal.Pulses[j+26] < PULSE3000) && (RawSignal.Pulses[j+26+26] > PULSE2500) ) { // first long delay found, make sure we have another at the right position
|
||||
for (i=0;i<26;i++){
|
||||
RawSignal.Pulses[1+i]=RawSignal.Pulses[j+1+i]; // reorder pulse array
|
||||
}
|
||||
RawSignal.Number=26; // New packet length
|
||||
RawSignal.Pulses[0]=72; // signal the plugin number that should process this packet
|
||||
return false; // Conversion done, stop plugin 1 and continue with regular plugins
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
// ==========================================================================
|
||||
|
||||
// ==========================================================================
|
||||
// End of Signal translation
|
||||
// ==========================================================================
|
||||
if (RawSignal.Number > OVERSIZED_LIMIT) { // unknown and unsupported long packet (290 is the max. pulse length used at the Oregon plugin)
|
||||
RawSignal.Number=0; // no need to show this to any of the other plugins for processing
|
||||
return true; // abort processing completely
|
||||
} // as there is no support for it anyway
|
||||
return false;
|
||||
}
|
||||
#endif //PLUGIN_001
|
||||
/*********************************************************************************************\
|
||||
167 5010
|
||||
77 2310
|
||||
52 1560
|
||||
|
||||
161
|
||||
77
|
||||
52
|
||||
|
||||
0137
|
||||
77
|
||||
52
|
||||
161
|
||||
77
|
||||
52
|
||||
169
|
||||
78
|
||||
52
|
||||
161
|
||||
77
|
||||
52
|
||||
0137
|
||||
77
|
||||
52
|
||||
161
|
||||
77
|
||||
52
|
||||
|
||||
|
||||
20;08;DEBUG;Pulses=511;Pulses(uSec)=
|
||||
|
||||
5010,2340,1560,210,270,510,270,510,270,540, 9
|
||||
270,510,270,510,270,510,270,510,270,510, 20
|
||||
270,510,270,510,270,510,270,510,270,510, 30
|
||||
270,510,270,510,270,510,600,210,270,510, 4
|
||||
270,510,270,510,270,540,270,540,600,210, 5
|
||||
600,210,600,210,270,510,270,540,270,540, 6
|
||||
270,510,270,510,270,510,270,510,600,210, 69
|
||||
600,210,600,210,600,210,600,210,600,210, 79
|
||||
270,510,270,510,600,210,4830,2310,1560,210,270,510,270,510,270,510,270,510,270,510,270,510,270,510,270,540,270,540,270,510,270,510,270,510,270,540,270,540,270,510,270,510,600,210,270,510,270,510,270,510,270,510,270,510,600,210,600,210,600,210,270,510,270,510,270,510,270,510,270,510,270,510,270,510,600,210,600,210,600,210,600,210,600,210,600,210,270,510,270,540,600,210,4830,2310,1560,210,270,510,270,510,270,510,270,540,270,510,270,510,270,510,270,510,270,510,270,510,270,510,270,510,270,510,270,510,270,510,270,510,600,210,270,510,270,510,270,510,270,510,270,510,600,210,600,210,600,210,270,540,270,540,270,510,270,510,270,510,270,510,270,510,600,210,600,210,600,210,600,210,600,210,600,210,270,510,270,510,600,210,4830,2310,1560,210,270,510,270,510,270,510,270,510,270,510,270,510,270,510,270,540,270,540,270,540,270,510,270,510,270,510,270,510,270,540,270,540,600,210,270,510,270,510,270,510,270,510,270,510,600,210,600,210,600,210,270,510,270,510,270,510,270,510,270,510,270,510,270,510,600,210,600,210,600,210,600,210,600,210,600,210,270,510,270,510,600,210,4830,2310,1560,210,270,540,270,510,270,510,270,510,270,510,270,510,270,510,270,510,270,510,270,510,270,510,270,510,270,510,270,510,270,510,270,510,600,210,270,510,270,510,270,510,270,510,270,540,600,210,600,210,600,210,270,510,270,510,270,510,270,540,270,540,270,510,270,510,600,210,600,210,600,210,600,210,600,210,600,210,270,510,270,510,600,210,4830,2310,1560,210,270,510,270,510,270,510,270,510,270,510,270,510,270,510,270,510,270,540,270,540,270,510,270,510,270,510,270,540,270,540,270,510,600,210,270,510,270,510,270,510,270,510,270,510,600,210,600,210,600,210,270,510,270,510,270,510,270,510,270,510,270,510,270,510,600,210,600,210,600,210,600,210,600,210,600,210,270;
|
||||
|
||||
|
||||
Plugin Pulselength
|
||||
------ -----------
|
||||
002 102-104
|
||||
003 50
|
||||
004 132 148
|
||||
005 50
|
||||
006 106
|
||||
007 66
|
||||
008 96
|
||||
009 66 68
|
||||
010 134-164
|
||||
011 100
|
||||
012 (26) 58
|
||||
013 42
|
||||
014 36-52
|
||||
015 116
|
||||
030 74
|
||||
031 94 & 126
|
||||
032 74-78
|
||||
034 124-284
|
||||
035 96
|
||||
040 58
|
||||
041 92/162/122/132
|
||||
042 48-56
|
||||
043 88
|
||||
044 82
|
||||
045 66
|
||||
046 74
|
||||
048 126-290
|
||||
060 26
|
||||
061 50
|
||||
070 36
|
||||
071 66
|
||||
072 26
|
||||
073 26
|
||||
074 50
|
||||
080 52
|
||||
081 46
|
||||
082 26
|
||||
090 194
|
||||
100 160 & 164-176
|
||||
\*********************************************************************************************/
|
|
@ -0,0 +1,220 @@
|
|||
//#######################################################################################################
|
||||
//## This Plugin is only for use with the RFLink software package ##
|
||||
//## Plugin-41 LaCrosse ##
|
||||
//#######################################################################################################
|
||||
/*********************************************************************************************\
|
||||
* This plugin takes care of decoding LaCrosse weatherstation outdoor sensors
|
||||
* It also works for all non LaCrosse sensors that follow this protocol.
|
||||
* Lacrosse WS2355, WS3600 and compatibles
|
||||
*
|
||||
* Author : StuntTeam
|
||||
* 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!
|
||||
*********************************************************************************************
|
||||
* Changelog: v1.0 initial release
|
||||
*********************************************************************************************
|
||||
* Technical information:
|
||||
* Partially based on http://makin-things.com/articles/decoding-lacrosse-weather-sensor-rf-transmissions/
|
||||
*
|
||||
* WS2355
|
||||
* Each packet is 52 bits long. 4 different packet formats are transmitted. They are composed of:
|
||||
*
|
||||
* data 0 1 2 3 4 5 6 7 8 9 10
|
||||
* 1) 0000 1001 01 00 00100010 01111000 01010011 0011 10101100 0001 0+9+4+2+2+7+8+5+3+3+A+C=41 = 1
|
||||
* 2) 0000 1001 00 01 00100010 01111000 01010000 1101 10101111 1000 0+9+1+2+2+7+8+5+0+D+A+F=48 = 8
|
||||
* 3) 0000 1001 00 10 00100010 01111000 00001000 1100 11110111 1000
|
||||
* 4) 0000 1001 01 11 00100010 01111000 00000000 1100 11111111 1101
|
||||
* SSSS PPPP QR AA BBBBBBBB CCCCCCCC DDDDDDDD dddd EEEEEEEE FFFF
|
||||
* 0000 1001 01 01 01100110 01011110 10001000 1001 01110111 0100
|
||||
* 0000 1001 00 11 01100110 01011110 00000000 1101 11111111 0110
|
||||
* 0000 1001 01 00 01100110 01011110 01000110 1000 10111001 0010
|
||||
* 0000 1001 00 01 01100110 01011110 01100111 1001 10011000 000 9+1+6+6+5+E+6+7+9+9+8=50 missing bit is 0
|
||||
0000 1001 01 11 01100110 01011110 00000000 1001 11111111 011 9+7+6+6+5+E+0+0+9+F+F=56 missing bit is 0
|
||||
* S = Sync
|
||||
* P = Preamble (1001 for WS2300, 0110 for WS3600?)
|
||||
* A = packet type 00=TEMP, 01=HUM, 10=RAIN, 11=WIND
|
||||
* B = Rolling Code
|
||||
* C = Flags
|
||||
* D = 12 bit value depending on the device/packet type
|
||||
* E = Inverted data
|
||||
* F = Checksum
|
||||
* Q = 0/1 1=windpacket reports windgust 0=windpacket reports windspeed
|
||||
* R = Error checking bit
|
||||
*
|
||||
* TEMP Dd = temperature - 30 degrees offset, 12 bits, 0x533 - 0x300 = 0x233 = 23.3 degrees
|
||||
* HUM D = humidity value, 8 bits, 0x50 = RH of 50
|
||||
* RAIN D = number of tips * 0.508mm (range=0-4095, Once the count reaches 4095 it wraps back to 0. Powerloss results in a reset of the count)
|
||||
* WIND d = Wind direction (0-15 in 22.5 degrees steps) D= wind speed
|
||||
*
|
||||
* Sample:
|
||||
* 20;D3;DEBUG;Pulses=104;Pulses(uSec)=1400,1300,1325,1300,1325,1275,1350,1150,225,1300,1325,1275,1325,1275,225,1300,1325,1275,225,1275,1350,1275,225,1300,1325,1275,225,1300,225,1275,1350,1275,1350,1275,250,1275,225,1275,1350,1275,1350,1300,225,1300,1350,1275,225,1275,225,1275,225,1275,225,1275,1325,1275,225,1300,1325,1275,1325,1275,1325,1275,250,1275,1350,1275,1325,1300,1325,1275,250,1275,1350,1275,1325,1275,250,1275,1325,1275,250,1275,225,1275,225,1275,1350,1275,225,1275,250,1275,225,1275,1325,1275,250,1275,1350,1300,1325;
|
||||
* 20;D4;DEBUG;Pulses=104;Pulses(uSec)=1400,1275,1350,1275,1350,1275,1325,1150,250,1275,1350,1275,1325,1275,250,1275,1325,1275,1350,1275,225,1275,225,1275,1350,1300,225,1275,225,1275,1350,1275,1325,1275,225,1275,225,1275,1325,1275,1325,1275,250,1275,1350,1300,225,1275,225,1275,225,1275,225,1275,1350,1275,1325,1275,1350,1275,1325,1275,1350,1275,1325,1275,1350,1275,1325,1300,1325,1275,225,1275,225,1275,1350,1275,225,1275,225,1300,225,1275,250,1275,225,1275,225,1275,250,1275,225,1275,225,1275,1350,1275,250,1275,225,1275,1325;
|
||||
* 20;D5;DEBUG;Pulses=104;Pulses(uSec)=1400,1275,1350,1275,1350,1275,1325,1150,225,1275,1350,1275,1325,1275,225,1300,1325,1275,225,1300,1325,1275,1325,1275,1350,1275,225,1300,225,1275,1350,1275,1350,1300,225,1300,225,1275,1350,1275,1325,1275,250,1275,1350,1275,250,1275,225,1275,225,1275,225,1275,1325,1275,1350,1275,250,1275,1325,1275,1350,1275,1350,1275,225,1275,225,1275,1350,1275,225,1300,1325,1275,1325,1275,1350,1275,250,1275,1325,1275,250,1275,250,1275,225,1275,1350,1275,1350,1275,225,1275,1350,1275,1350,1275,225,1275,1325;
|
||||
20;C3;DEBUG;Pulses=102;Pulses(uSec)=1400,1275,1325,1275,1325,1275,1325,1175,225,1300,1350,1275,1350,1275,225,1300,1325,1300,1325,1275,1325,1300,225,1300,1325,1275,225,1275,225,1300,1325,1275,1325,1275,250,1275,225,1275,1325,1275,1350,1275,225,1275,1325,1275,225,1225,300,1275,250,1275,225,1275,1325,1275,1325,1300,225,1275,225,1275,1325,1300,1325,1275,225,1275,225,1275,225,1275,225,1275,1325,1275,1325,1275,250,1275,250,1275,1325,1275,1350,1275,225,1275,225,1300,1325,1275,1350,1275,1325,1300,1325,1275,1350,1275,1325;
|
||||
20;E1;DEBUG;Pulses=102;Pulses(uSec)=1425,1275,1325,1275,1325,1275,1350,1150,225,1275,1350,1275,1350,1275,250,1275,1350,1275,225,1275,225,1275,250,1275,1350,1275,225,1300,225,1275,1325,1275,1350,1300,225,1275,225,1275,1350,1275,1325,1300,225,1275,1350,1275,250,1275,225,1275,225,1275,250,1275,1325,1275,1350,1275,1325,1275,1325,1275,1325,1275,1350,1275,1350,1275,1325,1300,1325,1275,250,1275,1325,1275,1325,1275,225,1275,250,1275,225,1275,250,1275,225,1300,225,1275,225,1275,225,1300,225,1275,1350,1275,250,1275,225;
|
||||
\*********************************************************************************************/
|
||||
#define LACROSSE_PULSECOUNT 104 // also handles 102 pulses!
|
||||
#define LACROSSE_PULSEMID 1000/RAWSIGNAL_SAMPLE_RATE
|
||||
#define LACROSSE_MIDLO 1100/RAWSIGNAL_SAMPLE_RATE
|
||||
#define LACROSSE_MIDHI 1400/RAWSIGNAL_SAMPLE_RATE
|
||||
|
||||
#ifdef PLUGIN_002
|
||||
boolean Plugin_002(byte function, char *string) {
|
||||
if ((RawSignal.Number != LACROSSE_PULSECOUNT) && (RawSignal.Number != (LACROSSE_PULSECOUNT-2))) return false;
|
||||
unsigned long bitstream1=0L; // holds first 16 bits
|
||||
unsigned long bitstream2=0L; // holds last 28 bits
|
||||
|
||||
unsigned int sensordata=0;
|
||||
byte checksum=0;
|
||||
byte bitcounter=0; // counts number of received bits (converted from pulses)
|
||||
byte sensortype=0;
|
||||
byte data[12];
|
||||
//==================================================================================
|
||||
// get bytes
|
||||
for(int x=1;x < RawSignal.Number;x+=2) {
|
||||
if ((RawSignal.Pulses[x+1] < LACROSSE_MIDLO) || (RawSignal.Pulses[x+1] > LACROSSE_MIDHI)) {
|
||||
if (x+1 < RawSignal.Number) return false; // in between pulse check
|
||||
}
|
||||
if (RawSignal.Pulses[x] > LACROSSE_PULSEMID ){
|
||||
if (bitcounter < 20) {
|
||||
bitstream1 = (bitstream1 << 1);
|
||||
bitcounter++; // only need to count the first 20 bits
|
||||
} else {
|
||||
bitstream2 = (bitstream2 << 1);
|
||||
}
|
||||
} else {
|
||||
if (bitcounter < 20) {
|
||||
bitstream1 = (bitstream1 << 1) | 0x1;
|
||||
bitcounter++; // only need to count the first 20 bits
|
||||
} else {
|
||||
bitstream2 = (bitstream2 << 1) | 0x1;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (RawSignal.Number == (LACROSSE_PULSECOUNT-2)) bitstream2 = (bitstream2 << 1); // add missing zero bit
|
||||
//==================================================================================
|
||||
// all bytes received, sort data, do sanity checks and make sure checksum is okay
|
||||
//==================================================================================
|
||||
if (bitstream1 == 0) return false;
|
||||
//if ((bitstream1 == 0) && (bitstream2 == 0)) return false;
|
||||
//data[0] = (bitstream1 >> 16) & 0x0f; // prepare nibbles from bit stream
|
||||
//if (data[0] != 0) return false; // just a quick check to make sure the sync bits are correct. they are not needed for the checksum
|
||||
data[0] = (bitstream1 >> 12) & 0x0f; // First nibble
|
||||
if ( (data[0] != 0x09) && (data[0] != 0x06) ) { // type verification
|
||||
return false; // 1001 for WS2300, 0110 for WS3600
|
||||
}
|
||||
data[1] = (bitstream1 >> 8) & 0x0f; // Various other checks are possible
|
||||
data[2] = (bitstream1 >> 4) & 0x0f; // Like parity checks and bit tests
|
||||
data[3] = (bitstream1 >> 0) & 0x0f; // but false positives do not seem to be a problem
|
||||
|
||||
data[4] = (bitstream2 >> 28) & 0x0f;
|
||||
data[5] = (bitstream2 >> 24) & 0x0f;
|
||||
data[6] = (bitstream2 >> 20) & 0x0f;
|
||||
data[7] = (bitstream2 >> 16) & 0x0f;
|
||||
data[8] = (bitstream2 >> 12) & 0x0f;
|
||||
data[9] = (bitstream2 >> 8) & 0x0f;
|
||||
data[10]= (bitstream2 >> 4) & 0x0f;
|
||||
//==================================================================================
|
||||
for (byte i=0;i<11;i++){
|
||||
checksum=checksum + data[i]; // max. value = A5
|
||||
}
|
||||
checksum=checksum & 0x0f;
|
||||
if (checksum != ((bitstream2)&0x0f)) return false;
|
||||
//==================================================================================
|
||||
// Prevent repeating signals from showing up
|
||||
//==================================================================================
|
||||
sensortype=(data[1])&0x03; // get sensor type from bitstream
|
||||
unsigned long tempval=((checksum)<<8)+sensortype; // sensor type + checksum
|
||||
if( (SignalHash!=SignalHashPrevious) || (RepeatingTimer<millis()) || (SignalCRC != tempval) ){
|
||||
SignalCRC=tempval; // not seen this RF packet recently, save value for later
|
||||
} else {
|
||||
return true; // already seen the RF packet recently
|
||||
}
|
||||
//==================================================================================
|
||||
// now process the various sensor types
|
||||
//==================================================================================
|
||||
// Output
|
||||
// ----------------------------------
|
||||
if (sensortype == 0x00) { // Temperature
|
||||
sensordata = data[6]*100; // 468
|
||||
sensordata = sensordata + data[7]*10;
|
||||
sensordata = sensordata + data[8];
|
||||
if ( (data[0]) == 0x09) { // WS2300
|
||||
sensordata = sensordata-300;
|
||||
} else { // WS3600
|
||||
sensordata = sensordata-400;
|
||||
}
|
||||
// ----------------------------------
|
||||
Serial.print("20;");
|
||||
PrintHexByte(PKSequenceNumber++);
|
||||
Serial.print(F(";LaCrosseV2;ID=")); // Label
|
||||
PrintHex8( data+2,2);
|
||||
// ----------------------------------
|
||||
sprintf(pbuffer, ";TEMP=%04x;", sensordata);
|
||||
Serial.println( pbuffer );
|
||||
} else
|
||||
if (sensortype == 0x01) { // Humidity
|
||||
sensordata=((data[6])<<4)+data[7];
|
||||
if (sensordata==0) return false; // Humidity should not be 0
|
||||
// ----------------------------------
|
||||
Serial.print("20;");
|
||||
PrintHexByte(PKSequenceNumber++);
|
||||
Serial.print(F(";LaCrosseV2;ID=")); // Label
|
||||
PrintHex8( data+2,2);
|
||||
// ----------------------------------
|
||||
sprintf(pbuffer, ";HUM=%02x;", (sensordata)&0xff);
|
||||
Serial.println( pbuffer );
|
||||
} else
|
||||
if (sensortype == 0x02) { // Rain
|
||||
unsigned long rain=((data[6])<<8)+((data[7])<<4)+(data[8]);
|
||||
if ( (data[0]) == 0x09) { // WS2300
|
||||
rain=rain*508; // 0-4095 * 0.508mm
|
||||
rain=rain/350; // divide by 3.5
|
||||
} else {
|
||||
rain=rain*518; // 0-4095 * 0.518mm
|
||||
rain=rain/100;
|
||||
}
|
||||
// ---------------------------------- // 8c = 140 = 140*0,518=72,5mm
|
||||
Serial.print("20;");
|
||||
PrintHexByte(PKSequenceNumber++);
|
||||
Serial.print(F(";LaCrosseV2;ID=00")); // Label
|
||||
PrintHex8( data+2,1);
|
||||
//PrintHex8( data+2,2);
|
||||
// ----------------------------------
|
||||
sprintf(pbuffer, ";RAIN=%04x;", (rain)&0xffff);
|
||||
Serial.println( pbuffer );
|
||||
} else
|
||||
if (sensortype == 0x03) { // Wind
|
||||
// ----------------------------------
|
||||
Serial.print("20;");
|
||||
PrintHexByte(PKSequenceNumber++);
|
||||
Serial.print(F(";LaCrosseV2;ID=")); // Label
|
||||
PrintHex8( data+2,2);
|
||||
// ----------------------------------
|
||||
sensordata=(data[8])&0x0f; // wind direction in 22.5 degree steps
|
||||
sprintf(pbuffer, ";WINDIR=%04d;", sensordata);
|
||||
Serial.print( pbuffer );
|
||||
|
||||
sensordata=((data[6])<<4)+data[7]; // possibly 9 bits?
|
||||
sensordata=sensordata * 36; // go from m/s to km/hr 6*36=216 = 21,6 km hr = 6 m/s
|
||||
if ( (data[0]) == 0x09) { // WS2300
|
||||
sensordata=sensordata / 10; // divide by 10
|
||||
}
|
||||
// 216 * 0,0277778
|
||||
sprintf(pbuffer, "WINGS=%04x;WINSP=%04x;", sensordata, sensordata);
|
||||
Serial.println( pbuffer );
|
||||
} else {
|
||||
Serial.print("20;");
|
||||
PrintHexByte(PKSequenceNumber++);
|
||||
Serial.print(F(";LaCrosseV2;DEBUG=")); // Label
|
||||
PrintHex8( data,11);
|
||||
Serial.println();
|
||||
//return false;
|
||||
}
|
||||
//==================================================================================
|
||||
RawSignal.Repeats=false;
|
||||
RawSignal.Number=0;
|
||||
return true;
|
||||
}
|
||||
#endif // PLUGIN_002
|
|
@ -0,0 +1,936 @@
|
|||
//#######################################################################################################
|
||||
//## This Plugin is only for use with the RFLink software package ##
|
||||
//## Plugin-03: Kaku (ARC) ##
|
||||
//#######################################################################################################
|
||||
/*********************************************************************************************\
|
||||
* This plugin takes care of sending and receiving the ARC protocol known from Klik-Aan-Klik-Uit (KAKU)
|
||||
* transmitter, switch, PIR, door sensor etc.
|
||||
* Devices following the ARC protocol can often be recognized by their manual switch settings for
|
||||
* the unit and house code number. Like for example by code wheel, dip switch or mini switch.
|
||||
*
|
||||
* This plugin also works with the following devices:
|
||||
* Princeton PT2262 / MOSDESIGN M3EB / Domia Lite / Klik-Aan-Klik-Uit / Intertechno / Sartano 2606.
|
||||
*
|
||||
* Author : StuntTeam & Jonas Jespersen (Sartano)
|
||||
* Support : http://sourceforge.net/projects/rflink/
|
||||
* License : This code is free for use in any open source project when this header is included.
|
||||
* 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!
|
||||
***********************************************************************************************
|
||||
* Address = A0..P16 according to KAKU adressing/notation
|
||||
***********************************************************************************************
|
||||
* Het signaal bestaat drie soorten reeksen van vier pulsen, te weten:
|
||||
* 0 = T,3T,T,3T, 1 = T,3T,3T,T, short 0 = T,3T,T,T Hierbij is iedere pulse (T) 350us PWDM
|
||||
*
|
||||
* KAKU Supports:
|
||||
* on/off, waarbij de pulsreeks er als volgt uit ziet: 000x en x staat voor Off / On
|
||||
* all on/off, waarbij de pulsreeks er als volgt uit ziet: 001x en x staat voor All Off / All On
|
||||
***********************************************************************************************
|
||||
* Brand Model Chipset Timing L/H
|
||||
* Intertechno ITK200 MDT10P61S 8/43
|
||||
* Profile PN-47N SC5262 5/26-27
|
||||
* Elro Home Comfort AB-600MA PT2262 7/29-30 6/30 6/31
|
||||
* Eurodomest 972080 HS2303
|
||||
* Elro Home Control AB-440 (Home Control) HX2262
|
||||
* Elro Home Control AB-4xx (Home Control) HX2272
|
||||
* Profile PN-44N SC2262 9/34
|
||||
* ProMax RSL366T SC5262 11/41 10/54 11/54 ?
|
||||
* Phenix YC-4000S HX2262
|
||||
* Flamingo FA500R 8/30
|
||||
* Select Remote 1728029 HS2262 3/22
|
||||
***********************************************************************************************
|
||||
* POSSIBLE BIT VARIATIONS: (Note: Bit order is reversed -compared to order in the RF signal- in the description below and in the processing!!!)
|
||||
* ------------------------ ( real: 1111 0000 011 1 => reversed: 1 110 0000 1111)
|
||||
* ARC with 0 & F bits:
|
||||
* -------------------
|
||||
* KAKU 1 110 0000 0000
|
||||
* Intertechno ITK200 D CCC BBBB AAAA
|
||||
* A bit 0-3 = address 2^4 = 16 addresses
|
||||
* B bit 4-7 = device 2^4 = 16 devices
|
||||
* C bit 8-10 = always (110) ! (AND with 0x700 result must be 0x600)
|
||||
* D bit 11 = on/off command (1=on 0=off)
|
||||
* Timing: 8-9 /33-34 (low/high)
|
||||
* Pulses: 0101 and 0110 eg. bit state 0 and f
|
||||
* 1 110 0000 0000 A1 on
|
||||
* 0 110 0000 0000 A1 off
|
||||
* 1 110 0001 0000 A2 on
|
||||
* 0 110 0001 0000 A2 off
|
||||
* 1 110 0010 0000 A3 on
|
||||
* 0 110 0010 0000 A3 off
|
||||
* 1 110 0011 0000 A4 on
|
||||
* 0 110 0011 0000 A4 off
|
||||
* 1 110 0000 0000 itk200 on
|
||||
* 0 110 0000 0000 itk200 off
|
||||
* -------------------
|
||||
* Perel 1 1111 1111 11 1
|
||||
* A BBBB CCCC DD E
|
||||
* A bit 0 = on/off command
|
||||
* B bit 1-4 = system code 1111 each bit corresponds to a button number
|
||||
* C bit 5-8 = device / Unitcode 1111 each bit corresponds to a button number
|
||||
* D bit 9-10 = always '11'
|
||||
* E bit 11 = on/off command (1=on 0=off)
|
||||
* Timing: 8-9 /33-34
|
||||
* Analyser: 362 / 1086
|
||||
* Pulses: 0101 and 0110 eg. bit state 0 and f
|
||||
* 1 110 100 1110 1 1 on
|
||||
* 0 110 100 1110 0 1 off
|
||||
* 1 110 101 1110 1 2 on
|
||||
* 0 110 101 1110 0 2 off
|
||||
* 1 110 110 1110 1 3 on
|
||||
* 0 110 110 1110 0 3 off
|
||||
* -------------------
|
||||
* Elro Home Easy 0 1 00001 10001
|
||||
* Elro Home Control D C BBBBB AAAAA
|
||||
* Brennenstuhl A bit 0-4 = address 2^5 = 32 addresses
|
||||
* Comfort B bit 5-9 = device
|
||||
* C bit 10 = unknown (always 1?)
|
||||
* D bit 11 = on/off command (1=on 0=off)
|
||||
* Timing: 7-8-9 /29-30
|
||||
* Pulses: 0101 and 0110 eg. bit state 0 and f
|
||||
* 1 1 10101 11000 I12 on
|
||||
* 0 1 10101 11000 I12 off
|
||||
* 1 1 10011 00000 A7 on
|
||||
* 0 1 10011 00000 A7 off
|
||||
* -------------------
|
||||
* AB400R 0 1 11111 11111
|
||||
* D C BBBBB AAAAA
|
||||
* A bit 0-4 = system code - each bit corresponds to a dip switch number (order 54321)
|
||||
* B bit 5-9 = device/unit code
|
||||
* C bit 10 = on/off command (reverse of D)
|
||||
* D bit 11 = on/off command
|
||||
* Timing: 8 /30
|
||||
* Analyser: 330/990
|
||||
* Pulses: 0101 and 0110 eg. bit state 0 and f
|
||||
* 10 11110 11110 A ON
|
||||
* 10 11101 11110 B ON
|
||||
* 10 11011 11110 C ON
|
||||
* 10 10111 11110 D ON
|
||||
* 01 11110 11110 A OFF
|
||||
* 01 11101 11110 B OFF
|
||||
* 01 11011 11110 C OFF
|
||||
* 01 10111 11110 D OFF
|
||||
* -------------------
|
||||
* Sartano: 0 1 00001 10001
|
||||
* Phenix YC-4000B D C BBBBB AAAAA
|
||||
* A bit 0-4 = address 2^5 = 32 addresses / Housecode
|
||||
* B bit 5-9 = device / Unitcode each bit corresponds to a button number
|
||||
* C bit 10 = off command (inverse command)
|
||||
* D bit 11 = on command
|
||||
* Timing: 11-12 /31-37
|
||||
* Pulses: 0101 and 0110 eg. bit state 0 and f
|
||||
* 01 01000 00000
|
||||
|
||||
* -------------------
|
||||
* ProMAX: 0 111 0000 0001
|
||||
* D CCC BBBB AAAA
|
||||
* A bit 0-3 = address 2^5 = 32 addresses / Housecode
|
||||
* B bit 4-7 = device / Unitcode 11111 each bit corresponds to a button number
|
||||
* C bit 8-10 = Always 111
|
||||
* D bit 11 = on command
|
||||
* Timing: 10-11 / 40-41
|
||||
* Pulses: 0101 and 0110 eg. bit state 0 and f
|
||||
* 111111101110 1 ON
|
||||
* 111111011110 2 ON
|
||||
* 111110111110 3 ON
|
||||
* 111101111110 4 ON
|
||||
|
||||
* 011111101110 1 OFF
|
||||
* 011111011110 2 OFF
|
||||
* 011110111110 3 OFF
|
||||
* 011101111110 4 OFF
|
||||
* -------------------
|
||||
* ProFile: 0 110 0001 0001
|
||||
* D CCC BBBB AAAA
|
||||
* A bit 0-3 = address 2^4 = 16 addresses / Housecode
|
||||
* B bit 4-7 = device / Unitcode 11111 each bit corresponds to a button number
|
||||
* C bit 8-10 = Always 110
|
||||
* D bit 11 = on command
|
||||
* Timing: 9/34
|
||||
* Pulses: 0101 and 0110 eg. bit state 0 and f
|
||||
* 111000000000 1 ON
|
||||
* 111000010000 2 ON
|
||||
* 111000100000 3 ON
|
||||
* 111000110000 4 ON
|
||||
* 011000000000 1 OFF
|
||||
* 011000010000 2 OFF
|
||||
* 011000100000 3 OFF
|
||||
* 011000110000 4 OFF
|
||||
* -------------------
|
||||
* ProFile:
|
||||
* Everflourish 0 110 0001 0001
|
||||
* EMW203 D CCC BBBB AAAA
|
||||
* A bit 0-3 = Button A/B/C/D
|
||||
* B bit 4-6 = Button 1/2/3
|
||||
* C bit 7-10 = Always 1111
|
||||
* D bit 11 = on/off command (on = tri-state)
|
||||
* Timing: 14/55
|
||||
* Analyser:
|
||||
* Pulses: 0101, 1010 and 0110 eg. bit state 0, 1 and f
|
||||
* 211111101110 A1 on
|
||||
* 211111011110 A2 on
|
||||
* 211110111110 A3 on
|
||||
* 211111101101 B1 on
|
||||
* 211111011101 B2 on
|
||||
* 211110111101 B3 on
|
||||
* 011111101110 A1 off
|
||||
* 011111011110 A2 off
|
||||
* 011110111110 A3 off
|
||||
* 011111101101 B1 off
|
||||
* 011111011101 B2 off
|
||||
* 011110111101 B3 off
|
||||
* -------------------
|
||||
|
||||
|
||||
* -------------------
|
||||
* 0 111 0000 1 000 reverse: 000 1 0000 111 0 and EF1 = 0?
|
||||
* A BBB CCCC D EEE
|
||||
* SelectRemote A/C/E = always 0 0000 000 !
|
||||
* Blokker: B bit 1-3 = device number
|
||||
* D bit 8 = on/off command
|
||||
* Timing: 0-1-2 /33-34
|
||||
* Analyser: 232 / 692
|
||||
* Pulses: 0101 and 1010 eg. bit state 0 and 1
|
||||
|
||||
* -------------------
|
||||
* 1111 111111 11
|
||||
* AAAA BBBBBB CC
|
||||
* Action: A bit 0-3 = address 2^4 = 16 addresses
|
||||
* Impuls B bit 4-9 = device
|
||||
* C bit 10-11= on/off command 10=on 01=off
|
||||
* -------------------
|
||||
* 10100 00010 0 0
|
||||
* AAAAA BBBBB C D
|
||||
* InterTechno A bit 0-4 = address 2^5 = 32 addresses
|
||||
* Düwi Terminal B bit 5-9 = device
|
||||
* Cogex C bit 10 = always 0
|
||||
* D bit 11 = on/off command
|
||||
* -------------------
|
||||
* 20;DB;DEBUG;Pulses=50;Pulses(uSec)=425,1050,250,1025,250,1025,250,1025,250,1025,250,1025,250,1025,250,1025,250,1050,250,1025,250,1025,250,1025,250,1025,250,1025,250,1025,250,1025,250,1050,250,1025,250,1025,950,300,250,1050,950,300,250,1025,950,300,250;
|
||||
*
|
||||
* KAKU Doorbell 010111101111
|
||||
* 20;07;DEBUG;Pulses=50;Pulses(uSec)=300,950,250,950,250,950,950,275,250,950,250,950,250,950,950,275,250,950,950,275,250,950,950,250,250,950,950,275,250,950,250,950,250,950,950,275,250,950,950,250,250,950,950,275,250,950,950,250,250;
|
||||
* 20;09;DEBUG;Pulses=50;Pulses(uSec)=3675,950,250,950,250,950,950,250,250,950,250,950,250,950,950,275,250,950,950,250,250,950,950,275,250,950,950,250,250,950,250,950,250,950,950,250,250,950,950,275,250,950,950,275,250,950,950,275,250;
|
||||
* HE842
|
||||
* 20;03;DEBUG;Pulses=50;Pulses(uSec)=270,870,840,240,210,870,840,240,210,870,210,870,210,870,840,240,210,870,210,870,210,870,210,870,210,870,210,870,210,870,840,240,210,870,210,870,210,870,840,240,210,870,840,240,210,870,210,870,210,6990;
|
||||
* 360/1380 12/46
|
||||
* 20;54;DEBUG;Pulses=50;Pulses(uSec)=1410,390,1350,360,1350,360,1380,360,1350,360,1380,360,1380,360,1380,360,1350,360,1350,360,1350,360,1380,360,1380,360,1380,360,1350,360,1380,360,1350,360,1350,360,390,1350,390,1350,390,1320,390,1320,420,1320,420,1320,390,6990;
|
||||
\*********************************************************************************************/
|
||||
#define KAKU_CodeLength 12 // number of data bits
|
||||
#define KAKU_R 300/RAWSIGNAL_SAMPLE_RATE //360 // 300 // 370? 350 us
|
||||
#define KAKU_PULSEMID 510/RAWSIGNAL_SAMPLE_RATE // (17) 510 = KAKU_R*2 not sufficient!
|
||||
|
||||
#ifdef PLUGIN_003
|
||||
boolean Plugin_003(byte function, char *string) {
|
||||
if (RawSignal.Number!=(KAKU_CodeLength*4)+2) return false; // conventionele KAKU bestaat altijd uit 12 data bits plus stop. Ongelijk, dan geen KAKU!
|
||||
if (RawSignal.Pulses[0]==15) return true; // Home Easy, skip KAKU
|
||||
if (RawSignal.Pulses[0]==63) return false; // No need to test, packet for plugin 63
|
||||
if (RawSignal.Pulses[0]==19) return false; // No need to test, packet for plugin 19
|
||||
// -------------------------------------------
|
||||
int i,j;
|
||||
boolean error=false;
|
||||
unsigned long bitstream=0L; // to store a 12 bit code (ARC type)
|
||||
unsigned long bitstream2=0L; // to store a 24 bit code (Extended ARC type)
|
||||
byte tricount=0;
|
||||
// -------------------------------------------
|
||||
byte command=0; // ON/OFF/DIM/BRIGHT
|
||||
byte group=0; // flags group command
|
||||
byte housecode=0; // 0x40 + 1 to 16? (41-5a?)
|
||||
byte unitcode=0; // 1 to 16
|
||||
// -------------------------------------------
|
||||
int PTLow=22; // Pulse Time - lowest found value (22 = a pulse duration of 550)
|
||||
int PTHigh=22; // Pulse Time - highest found value
|
||||
byte signaltype=0; // bit map: bit 0 = 0 bit 1 = f bit 2 = 0/1 (PT2262)
|
||||
// meaning: byte value 3 = kaku (bit 0/f) 5=PT2262 7=tristate 0/1/f
|
||||
byte devicetype=0; // 0=Kaku 5=Impuls 7=Perel
|
||||
// -------------------------------------------
|
||||
|
||||
// -------------------------------------------
|
||||
// ==========================================================================
|
||||
j=KAKU_PULSEMID; // set MID value
|
||||
j--;
|
||||
if (RawSignal.Pulses[0]==33) { // If device is "Impuls"
|
||||
RawSignal.Pulses[0]=0; // Unset Impuls conversion indicator
|
||||
j=KAKU_R; // Set new (LOWER!) MID value
|
||||
devicetype=5; // Indicate Impuls device
|
||||
}
|
||||
// -------------------------------------------
|
||||
if (RawSignal.Pulses[49] > j) return false; // Last pulse has to be low! Otherwise we are not dealing with an ARC signal
|
||||
// ==========================================================================
|
||||
// TIMING MEASUREMENT, this will find the shortest and longest pulse within the RF packet
|
||||
// ==========================================================================
|
||||
for (i=2;i<RawSignal.Number;i++) { // skip first pulse as it is often affected by the start bit pulse duration
|
||||
if(RawSignal.Pulses[i] < PTLow) { // shortest pulse?
|
||||
PTLow=RawSignal.Pulses[i]; // new value
|
||||
} else
|
||||
if(RawSignal.Pulses[i] > PTHigh) { // longest pulse?
|
||||
PTHigh=RawSignal.Pulses[i]; // new value
|
||||
}
|
||||
}
|
||||
// -------------------------------------------
|
||||
// TIMING MEASUREMENT to devicetype
|
||||
if (devicetype != 5) { // Dont do the timing check for Impuls, it is already identified at this point
|
||||
if( ((PTLow==7)||(PTLow==8)) && ((PTHigh ==30) || (PTHigh ==31) ) ) devicetype=4; // ELRO AB400
|
||||
if( ((PTLow==9)||(PTLow==10)) && ((PTHigh==36)||(PTHigh==37)||((PTHigh >=40)&&(PTHigh <=42))) ) devicetype=1; // ELRO AB600
|
||||
else
|
||||
if( ((PTLow==10)||(PTLow == 11)) && ((PTHigh >=40)&&(PTHigh <=42)) ) devicetype=2; // Profile PR44N / Promax rsl366t
|
||||
else
|
||||
if( (PTLow==13) && ((PTHigh >=32)&&(PTHigh <=34)) ) devicetype=3; // Profile PR47N
|
||||
else
|
||||
if( ((PTLow >=11)&&(PTLow <=12)) && ((PTHigh >=31)&&(PTHigh <=37)) ) devicetype=4; // Sartano
|
||||
else
|
||||
if( ((PTLow==12)||(PTLow==13)) && ((PTHigh==45)||(PTHigh==46)) ) devicetype=4; // Philips SBC
|
||||
else
|
||||
if( (PTLow <=3) && ((PTHigh==22)||(PTHigh==23)) ) devicetype=5; // Philips SBC
|
||||
//else
|
||||
//if( (PTLow == 8 || PTLow == 9) && (PTHigh == 33 || PTHigh == 34) ) devicetype=7; // Perel st=0,dt=7
|
||||
}
|
||||
//sprintf(pbuffer, "ST=%d DT=%d %d/%d",signaltype,devicetype,PTLow,PTHigh);
|
||||
//Serial.println( pbuffer );
|
||||
// ==========================================================================
|
||||
// Turn pulses into bits
|
||||
// -------------------------------------------
|
||||
for (i=0; i<KAKU_CodeLength; i++) {
|
||||
if (RawSignal.Pulses[4*i+1]<j && RawSignal.Pulses[4*i+2]>j && RawSignal.Pulses[4*i+3]<j && RawSignal.Pulses[4*i+4]>j) { // 0101
|
||||
bitstream=(bitstream >> 1); // bit '0'
|
||||
bitstream2=(bitstream2 << 2); // bit '0' written as '00'
|
||||
signaltype=signaltype|1; // bit '0' present in signal '0001'
|
||||
} else
|
||||
if (RawSignal.Pulses[4*i+1]<j && RawSignal.Pulses[4*i+2]>j && RawSignal.Pulses[4*i+3]>j && RawSignal.Pulses[4*i+4]<j) { // 0110
|
||||
//!! untested !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
|
||||
tricount++; // tri-state bit counter
|
||||
if ((i==11) && (tricount==1)) { // only the last bit, "on/off command" is in tristate mode? then it must be EMW200
|
||||
bitstream=(bitstream >> 1 | (1 << (KAKU_CodeLength-1))); // bit f (1)
|
||||
bitstream2=(bitstream2 << 2) | 2; // bit 'f' written as '10'
|
||||
// DONT CHANGE signal type to tri-state to keep EMW200 in KAKU mode
|
||||
} else {
|
||||
bitstream=(bitstream >> 1 | (1 << (KAKU_CodeLength-1))); // bit f (1)
|
||||
bitstream2=(bitstream2 << 2) | 2; // bit 'f' written as '10'
|
||||
signaltype=signaltype|2; // bit 'f' present in signal '0010'
|
||||
}
|
||||
} else
|
||||
if (RawSignal.Pulses[4*i+1]<j && RawSignal.Pulses[4*i+2]>j && RawSignal.Pulses[4*i+3]<j && RawSignal.Pulses[4*i+4]<j) { // 0100
|
||||
bitstream=(bitstream >> 1); // Short 0, Group command on 2nd bit. (NOT USED?!)
|
||||
bitstream2=(bitstream2 << 2) | 3; // bit 'short' written as '11'
|
||||
group=1;
|
||||
} else
|
||||
if (RawSignal.Pulses[4*i+1]>j && RawSignal.Pulses[4*i+2]<j && RawSignal.Pulses[4*i+3]>j && RawSignal.Pulses[4*i+4]<j) { // 1010
|
||||
bitstream2=(bitstream2 << 2) | 1; // bit '1' written as '01'
|
||||
signaltype=signaltype|4; // bit '1' present in signal '0100'
|
||||
if (devicetype==5) { // in case of 'impuls remote' store
|
||||
bitstream=(bitstream >> 1); // bit 1 (stored as 0) (IMPULS REMOTE)
|
||||
} else {
|
||||
if (i==11) { // last bit seems to cause trouble every now and then..?!
|
||||
bitstream=(bitstream >> 1); // bit 1 (stored as 0) (IMPULS REMOTE)
|
||||
} else {
|
||||
devicetype=6;
|
||||
bitstream=(bitstream >> 1 | (1 << (KAKU_CodeLength-1))); // bit f (1)
|
||||
}
|
||||
}
|
||||
} else {
|
||||
// -------------------------------------------
|
||||
// following are signal patches to fix bad transmission/receptions
|
||||
// -------------------------------------------
|
||||
if (i==0) { // are we dealing with a RTK/AB600 device? then the first bit is sometimes mistakenly seen as 1101
|
||||
bitstream2=(bitstream2 << 2); // bit 0
|
||||
if (RawSignal.Pulses[4*i+1]>j && RawSignal.Pulses[4*i+2]>j && RawSignal.Pulses[4*i+3]<j && RawSignal.Pulses[4*i+4]>j) { // 1101
|
||||
bitstream=(bitstream >> 1); // 0, treat as 0101 eg 0 bit
|
||||
} else {
|
||||
error=true;
|
||||
signaltype=signaltype|8;
|
||||
}
|
||||
} else {
|
||||
error=true;
|
||||
signaltype=signaltype|8;
|
||||
}
|
||||
} // bad signal
|
||||
}
|
||||
//==================================================================================
|
||||
// Sort out devices based on signal type and timing measurements
|
||||
// -------------------------------------------
|
||||
//sprintf(pbuffer, "ST=%d DT=%d [%d]",signaltype,devicetype, error);
|
||||
//Serial.println( pbuffer );
|
||||
//Serial.println(bitstream,BIN);
|
||||
//Serial.println(bitstream2,BIN);
|
||||
// -------------------------------------------
|
||||
// END OF TIMING MEASUREMENTS
|
||||
// ==========================================================================
|
||||
if (error==true) { // Error means that a pattern other than 0101/0110 was found
|
||||
return false; // This usually means we are dealing with a semi-compatible device
|
||||
} // that might have more states than used by ARC
|
||||
if ((signaltype != 0x03) && (signaltype != 0x05) && (signaltype != 0x07)) return false;
|
||||
//==================================================================================
|
||||
// Prevent repeating signals from showing up
|
||||
//==================================================================================
|
||||
//if( (SignalHash!=SignalHashPrevious) || ((RepeatingTimer+500)<millis()) ) {
|
||||
if( (SignalHash!=SignalHashPrevious) || ((RepeatingTimer+500)<millis()) || (((RepeatingTimer+1000)>millis())&&(SignalCRC != bitstream2)) ) {
|
||||
// not seen the RF packet recently
|
||||
if (signaltype == 0x07) {
|
||||
if (((RepeatingTimer+1000)>millis())&&(SignalCRC != bitstream2)) {
|
||||
return true; // skip tristate after normal arc
|
||||
}
|
||||
}
|
||||
//Serial.print("KAKU PREV:");
|
||||
//Serial.println(SignalHashPrevious);
|
||||
if ((SignalHashPrevious==14) && ((RepeatingTimer+2000)>millis()) ) {
|
||||
SignalHash=14;
|
||||
return true; // SignalHash 14 = HomeEasy, eg. cant switch KAKU after HE for 2 seconds
|
||||
}
|
||||
if ((SignalHashPrevious==11) && ((RepeatingTimer+2000)>millis()) ) {
|
||||
SignalHash=11;
|
||||
return true; // SignalHash 11 = FA500, eg. cant switch KAKU after FA500 for 2 seconds
|
||||
}
|
||||
SignalCRC=bitstream2; // store RF packet identifier
|
||||
} else {
|
||||
// already seen the RF packet recently
|
||||
return true;
|
||||
}
|
||||
//==================================================================================
|
||||
// Determine signal type to sort out the various houdecode/unitcode/button bits and on/off command bits
|
||||
//==================================================================================
|
||||
if (signaltype != 0x07) {
|
||||
if ((bitstream&0x700)!=0x600) { // valid but not real KAKU
|
||||
devicetype=4;
|
||||
}
|
||||
// -------------------------------------------
|
||||
if (devicetype == 4) { // Sartano
|
||||
// ---------------------------------- // Sartano
|
||||
housecode = ((bitstream) & 0x0000001FL); // .......11111b
|
||||
unitcode = (((bitstream) & 0x000003E0L) >> 5); // ..1111100000b
|
||||
housecode = ~housecode; // Sartano housecode is 5 bit ('A' - '`')
|
||||
housecode &= 0x0000001FL; // Translate housecode so that all jumpers off = 'A' and all jumpers on = '`'
|
||||
housecode += 0x41;
|
||||
switch(unitcode) { // Translate unit code into button number 1 - 5
|
||||
case 0x1E: // E=1110
|
||||
unitcode = 1;
|
||||
break;
|
||||
case 0x1D: // D=1101
|
||||
unitcode = 2;
|
||||
break;
|
||||
case 0x1B: // B=1011
|
||||
unitcode = 3;
|
||||
break;
|
||||
case 0x17: // 7=0111
|
||||
unitcode = 4;
|
||||
break;
|
||||
case 0x0F: // f=1111
|
||||
unitcode = 5;
|
||||
break;
|
||||
default:
|
||||
//Serial.print("Sartano:");
|
||||
devicetype=3; // invalid for Sartano, fall back
|
||||
break;
|
||||
}
|
||||
if (devicetype == 4) { // Sartano
|
||||
if ( ((bitstream >> 10) & 0x03) == 2) {
|
||||
command = 1; // On
|
||||
} else if ( ((bitstream >> 10) & 0x03) == 1){
|
||||
command = 0;// Off
|
||||
}
|
||||
}
|
||||
} else
|
||||
// -------------------------------------------
|
||||
if (devicetype == 5) { // IMPULS
|
||||
housecode = ((bitstream) & 0x0000000FL); // ........1111b
|
||||
unitcode = (((bitstream) & 0x000003F0L) >> 4); // ..1111110000b
|
||||
housecode = ~housecode; // Impuls housecode is 4 bit ('A' - 'P')
|
||||
housecode &= 0x0000000FL; // Translate housecode so that all jumpers off = 'A' and all jumpers on = 'P'
|
||||
housecode += 0x41;
|
||||
unitcode = ~unitcode; // Impuls unitcode is 5 bit
|
||||
unitcode &= 0x0000001FL; // Translate unitcode so that all jumpers off = '1' and all jumpers on = '64'
|
||||
if ( ((bitstream >> 10) & 0x03) == 2) {
|
||||
command = 0; // Off
|
||||
} else
|
||||
if ( ((bitstream >> 10) & 0x03) == 1){
|
||||
command = 1;// On
|
||||
}
|
||||
} else
|
||||
// -------------------------------------------
|
||||
if (devicetype == 6) { // Blokker/SelectRemote
|
||||
// ----------------------------------
|
||||
if ( ((bitstream)&0xef1) != 0) return false; // Not a valid bitstream
|
||||
|
||||
housecode = ((bitstream) & 0x0000000EL); // Isolate housecode
|
||||
housecode = housecode >> 1; // shift right 1 bit
|
||||
housecode = (~housecode)&0x07; // invert bits
|
||||
housecode += 0x41; // add 'A'
|
||||
unitcode = 0;
|
||||
|
||||
if ( ((bitstream >> 8) & 0x01) == 1) {
|
||||
command = 1; // On
|
||||
} else {
|
||||
command = 0;// Off
|
||||
}
|
||||
// ---------------------------------- // Sartano
|
||||
} else
|
||||
// -------------------------------------------
|
||||
if (devicetype != 4) { // KAKU (and some compatibles for now)
|
||||
// ----------------------------------
|
||||
if ((bitstream&0x700)!=0x600) { // valid but not real KAKU
|
||||
housecode=(((bitstream) &0x0f) +0x41);
|
||||
unitcode=((((bitstream) &0xf0) >> 4)+1);
|
||||
devicetype=1;
|
||||
} else {
|
||||
if ((bitstream&0x600)!=0x600) {
|
||||
//Serial.println("Kaku 0/1 error");
|
||||
return false; // use two static bits as checksum
|
||||
}
|
||||
//bitstream=(bitstream)&0xffe; // kill bit to ensure Perel works -> actually kills code wheel letter B
|
||||
housecode=(((bitstream) &0x0f) +0x41);
|
||||
unitcode=((((bitstream) &0xf0) >> 4)+1);
|
||||
// ----------------------------------
|
||||
}
|
||||
if ( ((bitstream >> 11) & 0x01) == 1) {
|
||||
command=1; // ON
|
||||
} else {
|
||||
command=0; // OFF
|
||||
}
|
||||
}
|
||||
}
|
||||
// ==========================================================================
|
||||
// Output
|
||||
// ----------------------------------
|
||||
sprintf(pbuffer, "20;%02X;", PKSequenceNumber++); // Node and packet number
|
||||
Serial.print( pbuffer );
|
||||
// ----------------------------------
|
||||
if (signaltype == 0x03) { // '0011' bits indicate bits 0 and f are used in the signal
|
||||
if (devicetype < 4) { // KAKU (and some compatibles for now)
|
||||
Serial.print(F("Kaku;")); // Label
|
||||
} else {
|
||||
if (devicetype == 4) { // AB440R and Sartano
|
||||
Serial.print(F("AB400D;")); // Label
|
||||
} else
|
||||
if (devicetype == 5) { // Impuls
|
||||
Serial.print(F("Impuls;")); // Label
|
||||
} else {
|
||||
Serial.print(F("Sartano;")); // Others
|
||||
}
|
||||
}
|
||||
} else
|
||||
if (signaltype == 0x05) { // '0101' bits indicate bits 0 and 1 are used in the signal
|
||||
if (devicetype == 5) { // KAKU (and some compatibles for now)
|
||||
Serial.print(F("Impuls;")); // Label
|
||||
} else {
|
||||
Serial.print(F("PT2262;")); // Label
|
||||
}
|
||||
} else
|
||||
if (signaltype == 0x07) { // '0111' bits indicate bits 0, f and 1 are used in the signal (tri-state)
|
||||
Serial.print(F("TriState;")); // Label
|
||||
}
|
||||
// ----------------------------------
|
||||
if (signaltype == 0x07) { // '0111' bits indicate bits 0, f and 1 are used in the signal (tri-state)
|
||||
sprintf(pbuffer, "ID=%06lx;",((bitstream2)>>4)&0xffffff) ; // ID
|
||||
Serial.print( pbuffer );
|
||||
housecode=(bitstream2)&0x03;
|
||||
unitcode=((((bitstream2)>>2)&0x03)^0x03)^housecode;
|
||||
//command=((bitstream2)&1)^1; << ^1 reverses lidl light
|
||||
command=((bitstream2)&3); // 00 01 10 0 1 f
|
||||
if (command > 1) command=1; // 0 stays 0 (OFF), 1 and f become 1 (ON)
|
||||
} else {
|
||||
sprintf(pbuffer, "ID=%02x;", housecode); // ID
|
||||
Serial.print( pbuffer );
|
||||
}
|
||||
sprintf(pbuffer, "SWITCH=%d;", unitcode);
|
||||
Serial.print( pbuffer );
|
||||
Serial.print(F("CMD="));
|
||||
if (group==1) Serial.print(F("ALL"));
|
||||
if ( command == 1 ) {
|
||||
Serial.print(F("ON;"));
|
||||
} else {
|
||||
Serial.print(F("OFF;"));
|
||||
}
|
||||
Serial.println();
|
||||
// ----------------------------------
|
||||
RawSignal.Repeats=true; // suppress repeats of the same RF packet
|
||||
RawSignal.Number=0;
|
||||
return true;
|
||||
}
|
||||
#endif //PLUGIN_003
|
||||
|
||||
#ifdef PLUGIN_TX_003
|
||||
void Arc_Send(unsigned long address); // sends 0 and float
|
||||
void NArc_Send(unsigned long bitstream); // sends 0 and 1
|
||||
void TriState_Send(unsigned long bitstream); // sends 0, 1 and float
|
||||
|
||||
boolean PluginTX_003(byte function, char *string) {
|
||||
boolean success=false;
|
||||
unsigned long bitstream=0L;
|
||||
byte command=0;
|
||||
uint32_t housecode = 0;
|
||||
uint32_t unitcode = 0;
|
||||
byte Home=0; // KAKU home A..P
|
||||
byte Address=0; // KAKU Address 1..16
|
||||
byte c=0;
|
||||
byte x=0;
|
||||
// ==========================================================================
|
||||
//10;Kaku;00004d;1;OFF;
|
||||
//10;Kaku;00004f;e;ON;
|
||||
//10;Kaku;000050;10;ON;
|
||||
//10;Kaku;000049;b;ON;
|
||||
//012345678901234567890
|
||||
// ==========================================================================
|
||||
if (strncasecmp(InputBuffer_Serial+3,"KAKU;",5) == 0) { // KAKU Command eg. Kaku;A1;On
|
||||
if (InputBuffer_Serial[14] != ';') return false;
|
||||
|
||||
x=15; // character pointer
|
||||
InputBuffer_Serial[10]=0x30;
|
||||
InputBuffer_Serial[11]=0x78; // Get home from hexadecimal value
|
||||
InputBuffer_Serial[14]=0x00; // Get home from hexadecimal value
|
||||
Home=str2int(InputBuffer_Serial+10); // KAKU home A is intern 0
|
||||
if (Home < 0x51) // take care of upper/lower case
|
||||
Home=Home - 'A';
|
||||
else
|
||||
if (Home < 0x71) // take care of upper/lower case
|
||||
Home=Home - 'a';
|
||||
else {
|
||||
return false; // invalid value
|
||||
}
|
||||
|
||||
while((c=InputBuffer_Serial[x++])!=';'){ // Address: 1 to 16/32
|
||||
if(c>='0' && c<='9'){Address=Address*10;Address=Address+c-'0';}
|
||||
if(c>='a' && c<='f'){Address=Address+(c-'a'+10);} // 31?
|
||||
if(c>='A' && c<='F'){Address=Address+(c-'A'+10);} // 51?
|
||||
}
|
||||
//if (Address==0) { // group command is given: 0=all
|
||||
// command=2; // Set 2nd bit for group.
|
||||
// bitstream=Home;
|
||||
//} else {
|
||||
// bitstream= Home | ((Address-1)<<4);
|
||||
//}
|
||||
|
||||
bitstream= Home | ((Address-1)<<4);
|
||||
command |= str2cmd(InputBuffer_Serial+x)==VALUE_ON; // ON/OFF command
|
||||
bitstream = bitstream | (0x600 | ((command & 1) << 11)); // create the bitstream
|
||||
//Serial.println(bitstream);
|
||||
Arc_Send(bitstream);
|
||||
success=true;
|
||||
// --------------- END KAKU SEND ------------
|
||||
} else
|
||||
// ==========================================================================
|
||||
//10;AB400D;00004d;1;OFF;
|
||||
//012345678901234567890
|
||||
// ==========================================================================
|
||||
if (strncasecmp(InputBuffer_Serial+3,"AB400D;",7) == 0) { // KAKU Command eg. Kaku;A1;On
|
||||
if (InputBuffer_Serial[16] != ';') return false;
|
||||
x=17; // character pointer
|
||||
InputBuffer_Serial[12]=0x30;
|
||||
InputBuffer_Serial[13]=0x78; // Get home from hexadecimal value
|
||||
InputBuffer_Serial[16]=0x00; // Get home from hexadecimal value
|
||||
Home=str2int(InputBuffer_Serial+12); // KAKU home A is intern 0
|
||||
if (Home < 0x61) // take care of upper/lower case
|
||||
Home=Home - 'A';
|
||||
else
|
||||
if (Home < 0x81) // take care of upper/lower case
|
||||
Home=Home - 'a';
|
||||
else {
|
||||
return false; // invalid value
|
||||
}
|
||||
while((c=InputBuffer_Serial[x++])!=';'){ // Address: 1 to 16/32
|
||||
if(c>='0' && c<='9'){Address=Address*10;Address=Address+c-'0';}
|
||||
}
|
||||
command = str2cmd(InputBuffer_Serial+x)==VALUE_ON; // ON/OFF command
|
||||
housecode = ~Home;
|
||||
housecode &= 0x0000001FL;
|
||||
unitcode=Address;
|
||||
if ((unitcode >= 1) && (unitcode <= 5) ) {
|
||||
bitstream = housecode & 0x0000001FL;
|
||||
if (unitcode == 1) bitstream |= 0x000003C0L;
|
||||
else if (unitcode == 2) bitstream |= 0x000003A0L;
|
||||
else if (unitcode == 3) bitstream |= 0x00000360L;
|
||||
else if (unitcode == 4) bitstream |= 0x000002E0L;
|
||||
else if (unitcode == 5) bitstream |= 0x000001E0L;
|
||||
|
||||
if (command) bitstream |= 0x00000800L;
|
||||
else bitstream |= 0x00000400L;
|
||||
}
|
||||
//Serial.println(bitstream);
|
||||
Arc_Send(bitstream);
|
||||
success=true;
|
||||
} else
|
||||
// --------------- END SARTANO SEND ------------
|
||||
// ==========================================================================
|
||||
//10;PT2262;000041;1;OFF;
|
||||
//012345678901234567890
|
||||
// ==========================================================================
|
||||
if (strncasecmp(InputBuffer_Serial+3,"PT2262;",7) == 0) { // KAKU Command eg. Kaku;A1;On
|
||||
if (InputBuffer_Serial[16] != ';') return false;
|
||||
x=17; // character pointer
|
||||
InputBuffer_Serial[12]=0x30;
|
||||
InputBuffer_Serial[13]=0x78; // Get home from hexadecimal value
|
||||
InputBuffer_Serial[16]=0x00; // Get home from hexadecimal value
|
||||
Home=str2int(InputBuffer_Serial+12); // KAKU home A is intern 0
|
||||
if (Home < 0x61) // take care of upper/lower case
|
||||
Home=Home - 'A';
|
||||
else
|
||||
if (Home < 0x81) // take care of upper/lower case
|
||||
Home=Home - 'a';
|
||||
else {
|
||||
return false; // invalid value
|
||||
}
|
||||
while((c=InputBuffer_Serial[x++])!=';'){ // Address: 1 to 16/32
|
||||
if(c>='0' && c<='9'){Address=Address*10;Address=Address+c-'0';}
|
||||
}
|
||||
// reconstruct bitstream reversed order so that most right bit can be send first
|
||||
command = str2cmd(InputBuffer_Serial+x)==VALUE_ON; // ON/OFF command
|
||||
housecode = ~Home;
|
||||
housecode &= 0x00000007L;
|
||||
housecode=(housecode)<<1;
|
||||
if (command) bitstream |= 0x00000100L;
|
||||
NArc_Send(bitstream); // send 24 bits tristate signal (0/1/f)
|
||||
success=true;
|
||||
} else
|
||||
// --------------- END Select Remote SEND ------------
|
||||
// ==========================================================================
|
||||
//10;TriState;00004d;1;OFF;
|
||||
//10;TriState;08000a;2;OFF; 20;1B;TriState;ID=08000a;SWITCH=2;CMD=OFF;
|
||||
//10;TriState;0a6980;2;OFF;
|
||||
//01234567890123456789012
|
||||
// ==========================================================================
|
||||
if (strncasecmp(InputBuffer_Serial+3,"TriState;",9) == 0) { // KAKU Command eg. Kaku;A1;On
|
||||
if (InputBuffer_Serial[18] != ';') return false;
|
||||
x=19; // character pointer
|
||||
InputBuffer_Serial[10]=0x30;
|
||||
InputBuffer_Serial[11]=0x78; // Get home from hexadecimal value
|
||||
InputBuffer_Serial[18]=0x00; // Get home from hexadecimal value
|
||||
bitstream=str2int(InputBuffer_Serial+10); // KAKU home A is intern 0
|
||||
bitstream=(bitstream<<4);
|
||||
|
||||
// 11^00^01=10 11^10^11=01 11^11^00=00
|
||||
while((c=InputBuffer_Serial[x++])!=';'){ // Address: 0/1/2
|
||||
if(c>='0' && c<='9'){Address=Address*10;Address=Address+c-'0';}
|
||||
}
|
||||
Address=(Address)&0x03; // only use 3 bits
|
||||
command = str2cmd(InputBuffer_Serial+x); // ON/OFF command
|
||||
if (command==VALUE_ON) { // on
|
||||
if (Address==0x0) bitstream |= 0x0000000bL; // 0011
|
||||
if (Address==0x1) bitstream |= 0x0000000cL; // 1011
|
||||
if (Address==0x2) bitstream |= 0x00000001L; // 0001
|
||||
} else { // off
|
||||
if (Address==0x0) bitstream |= 0x0000000cL; // 1100
|
||||
if (Address==0x1) bitstream |= 0x0000000eL; // 1110
|
||||
if (Address==0x2) bitstream |= 0x00000004L; // 0100
|
||||
}
|
||||
TriState_Send(bitstream);
|
||||
success=true;
|
||||
} else
|
||||
// --------------- END TRISTATE SEND ------------
|
||||
// ==========================================================================
|
||||
//10;Impuls;00004d;1;OFF;
|
||||
//012345678901234567890
|
||||
// ==========================================================================
|
||||
if (strncasecmp(InputBuffer_Serial+3,"Impuls;",7) == 0) { // KAKU Command eg. Kaku;A1;On
|
||||
if (InputBuffer_Serial[16] != ';') return false;
|
||||
x=17; // character pointer
|
||||
InputBuffer_Serial[12]=0x30;
|
||||
InputBuffer_Serial[13]=0x78; // Get home from hexadecimal value
|
||||
InputBuffer_Serial[16]=0x00; // Get home from hexadecimal value
|
||||
Home=str2int(InputBuffer_Serial+12); // KAKU home A is intern 0
|
||||
if (Home < 0x61) // take care of upper/lower case
|
||||
Home=Home - 'A';
|
||||
else
|
||||
if (Home < 0x81) // take care of upper/lower case
|
||||
Home=Home - 'a';
|
||||
else {
|
||||
return false; // invalid value
|
||||
}
|
||||
while((c=InputBuffer_Serial[x++])!=';'){ // Address: 1 to 16/32
|
||||
if(c>='0' && c<='9'){Address=Address*10;Address=Address+c-'0';}
|
||||
}
|
||||
command = str2cmd(InputBuffer_Serial+x)==VALUE_ON; // ON/OFF command
|
||||
housecode = ~Home;
|
||||
housecode &= 0x0000001FL;
|
||||
unitcode=Address;
|
||||
if ((unitcode >= 1) && (unitcode <= 5) ) {
|
||||
bitstream = housecode & 0x0000001FL;
|
||||
if (unitcode == 1) bitstream |= 0x000003C0L;
|
||||
else if (unitcode == 2) bitstream |= 0x000003A0L;
|
||||
else if (unitcode == 3) bitstream |= 0x00000360L;
|
||||
else if (unitcode == 4) bitstream |= 0x000002E0L;
|
||||
else if (unitcode == 5) bitstream |= 0x000001E0L;
|
||||
|
||||
if (command) bitstream |= 0x00000800L;
|
||||
else bitstream |= 0x00000400L;
|
||||
}
|
||||
TriState_Send(bitstream);
|
||||
success=true;
|
||||
}
|
||||
return success;
|
||||
}
|
||||
|
||||
//#define KAKU_T 390 //420 // 370 // 370? 350 us
|
||||
//#define Sartano_T 300 //360 // 300 // 300 uS
|
||||
|
||||
void Arc_Send(unsigned long bitstream) {
|
||||
int fpulse = 360; // Pulse width in microseconds
|
||||
int fretrans = 8; // Number of code retransmissions
|
||||
uint32_t fdatabit;
|
||||
uint32_t fdatamask = 0x00000001;
|
||||
uint32_t fsendbuff;
|
||||
|
||||
digitalWrite(PIN_RF_RX_VCC,LOW); // Turn off power to the RF receiver
|
||||
digitalWrite(PIN_RF_TX_VCC,HIGH); // Enable the 433Mhz transmitter
|
||||
delayMicroseconds(TRANSMITTER_STABLE_DELAY); // short delay to let the transmitter become stable (Note: Aurel RTX MID needs 500µS/0,5ms)
|
||||
|
||||
for (int nRepeat = 0; nRepeat <= fretrans; nRepeat++) {
|
||||
fsendbuff = bitstream;
|
||||
// Send command
|
||||
|
||||
for (int i = 0; i < 12; i++) { // Arc packet is 12 bits
|
||||
// read data bit
|
||||
fdatabit = fsendbuff & fdatamask; // Get most right bit
|
||||
fsendbuff = (fsendbuff >> 1); // Shift right
|
||||
|
||||
// PT2262 data can be 0, 1 or float. Only 0 and float is used by regular ARC
|
||||
if (fdatabit != fdatamask) { // Write 0
|
||||
digitalWrite(PIN_RF_TX_DATA, HIGH);
|
||||
delayMicroseconds(fpulse * 1);
|
||||
digitalWrite(PIN_RF_TX_DATA, LOW);
|
||||
delayMicroseconds(fpulse * 3);
|
||||
digitalWrite(PIN_RF_TX_DATA, HIGH);
|
||||
delayMicroseconds(fpulse * 1);
|
||||
digitalWrite(PIN_RF_TX_DATA, LOW);
|
||||
delayMicroseconds(fpulse * 3);
|
||||
} else { // Write float
|
||||
digitalWrite(PIN_RF_TX_DATA, HIGH);
|
||||
delayMicroseconds(fpulse * 1);
|
||||
digitalWrite(PIN_RF_TX_DATA, LOW);
|
||||
delayMicroseconds(fpulse * 3);
|
||||
digitalWrite(PIN_RF_TX_DATA, HIGH);
|
||||
delayMicroseconds(fpulse * 3);
|
||||
digitalWrite(PIN_RF_TX_DATA, LOW);
|
||||
delayMicroseconds(fpulse * 1);
|
||||
}
|
||||
}
|
||||
// Send sync bit
|
||||
digitalWrite(PIN_RF_TX_DATA, HIGH);
|
||||
delayMicroseconds(fpulse * 1);
|
||||
digitalWrite(PIN_RF_TX_DATA, LOW); // and lower the signal
|
||||
delayMicroseconds(fpulse * 31);
|
||||
}
|
||||
delayMicroseconds(TRANSMITTER_STABLE_DELAY); // short delay to let the transmitter become stable (Note: Aurel RTX MID needs 500µS/0,5ms)
|
||||
digitalWrite(PIN_RF_TX_VCC,LOW); // Turn the 433Mhz transmitter off
|
||||
digitalWrite(PIN_RF_RX_VCC,HIGH); // Turn the 433Mhz receiver on
|
||||
RFLinkHW();
|
||||
}
|
||||
|
||||
void NArc_Send(unsigned long bitstream) {
|
||||
int fpulse = 190; // Pulse width in microseconds
|
||||
int fretrans = 7; // Number of code retransmissions
|
||||
uint32_t fdatabit;
|
||||
uint32_t fdatamask = 0x00000001;
|
||||
uint32_t fsendbuff;
|
||||
|
||||
digitalWrite(PIN_RF_RX_VCC,LOW); // Turn off power to the RF receiver
|
||||
digitalWrite(PIN_RF_TX_VCC,HIGH); // Enable the 433Mhz transmitter
|
||||
delayMicroseconds(TRANSMITTER_STABLE_DELAY); // short delay to let the transmitter become stable (Note: Aurel RTX MID needs 500µS/0,5ms)
|
||||
|
||||
for (int nRepeat = 0; nRepeat <= fretrans; nRepeat++) {
|
||||
fsendbuff = bitstream;
|
||||
// Send command
|
||||
|
||||
for (int i = 0; i < 12; i++) { // Arc packet is 12 bits
|
||||
// read data bit
|
||||
fdatabit = fsendbuff & fdatamask; // Get most right bit
|
||||
fsendbuff = (fsendbuff >> 1); // Shift right
|
||||
|
||||
// PT2262 data can be 0, 1 or float. Only 0 and float is used by regular ARC
|
||||
if (fdatabit != fdatamask) { // Write 0
|
||||
digitalWrite(PIN_RF_TX_DATA, HIGH);
|
||||
delayMicroseconds(fpulse * 1);
|
||||
digitalWrite(PIN_RF_TX_DATA, LOW);
|
||||
delayMicroseconds(fpulse * 3);
|
||||
digitalWrite(PIN_RF_TX_DATA, HIGH);
|
||||
delayMicroseconds(fpulse * 1);
|
||||
digitalWrite(PIN_RF_TX_DATA, LOW);
|
||||
delayMicroseconds(fpulse * 3);
|
||||
} else { // Write 1
|
||||
digitalWrite(PIN_RF_TX_DATA, HIGH);
|
||||
delayMicroseconds(fpulse * 3);
|
||||
digitalWrite(PIN_RF_TX_DATA, LOW);
|
||||
delayMicroseconds(fpulse * 1);
|
||||
digitalWrite(PIN_RF_TX_DATA, HIGH);
|
||||
delayMicroseconds(fpulse * 3);
|
||||
digitalWrite(PIN_RF_TX_DATA, LOW);
|
||||
delayMicroseconds(fpulse * 1);
|
||||
}
|
||||
}
|
||||
// Send sync bit
|
||||
digitalWrite(PIN_RF_TX_DATA, HIGH);
|
||||
delayMicroseconds(fpulse * 1);
|
||||
digitalWrite(PIN_RF_TX_DATA, LOW); // and lower the signal
|
||||
delayMicroseconds(fpulse * 31);
|
||||
}
|
||||
delayMicroseconds(TRANSMITTER_STABLE_DELAY); // short delay to let the transmitter become stable (Note: Aurel RTX MID needs 500µS/0,5ms)
|
||||
digitalWrite(PIN_RF_TX_VCC,LOW); // Turn thew 433Mhz transmitter off
|
||||
digitalWrite(PIN_RF_RX_VCC,HIGH); // Turn the 433Mhz receiver on
|
||||
RFLinkHW();
|
||||
}
|
||||
|
||||
void TriState_Send(unsigned long bitstream) {
|
||||
int fpulse = 360; // Pulse width in microseconds
|
||||
int fretrans = 8; // Number of code retransmissions
|
||||
uint32_t fdatabit;
|
||||
uint32_t fdatamask = 0x00000003;
|
||||
uint32_t fsendbuff;
|
||||
|
||||
digitalWrite(PIN_RF_RX_VCC,LOW); // Turn off power to the RF receiver
|
||||
digitalWrite(PIN_RF_TX_VCC,HIGH); // Enable the 433Mhz transmitter
|
||||
delayMicroseconds(TRANSMITTER_STABLE_DELAY); // short delay to let the transmitter become stable (Note: Aurel RTX MID needs 500µS/0,5ms)
|
||||
|
||||
// reverse data bits (2 by 2)
|
||||
for (unsigned short i=0; i<12; i++) { // reverse data bits (12 times 2 bits = 24 bits in total)
|
||||
fsendbuff<<=2;
|
||||
fsendbuff|=(bitstream & B11);
|
||||
bitstream>>=2;
|
||||
}
|
||||
bitstream=fsendbuff; // store result
|
||||
|
||||
for (int nRepeat = 0; nRepeat <= fretrans; nRepeat++) {
|
||||
fsendbuff = bitstream;
|
||||
// Send command
|
||||
for (int i = 0; i < 12; i++) { // 12 times 2 bits = 24 bits in total
|
||||
// read data bit
|
||||
fdatabit = fsendbuff & fdatamask; // Get most right 2 bits
|
||||
fsendbuff = (fsendbuff >> 2); // Shift right
|
||||
// data can be 0, 1 or float.
|
||||
if (fdatabit == 0) { // Write 0
|
||||
digitalWrite(PIN_RF_TX_DATA, HIGH);
|
||||
delayMicroseconds(fpulse);
|
||||
digitalWrite(PIN_RF_TX_DATA, LOW);
|
||||
delayMicroseconds(fpulse * 3);
|
||||
digitalWrite(PIN_RF_TX_DATA, HIGH);
|
||||
delayMicroseconds(fpulse);
|
||||
digitalWrite(PIN_RF_TX_DATA, LOW);
|
||||
delayMicroseconds(fpulse * 3);
|
||||
} else
|
||||
if (fdatabit == 1) { // Write 1
|
||||
digitalWrite(PIN_RF_TX_DATA, HIGH);
|
||||
delayMicroseconds(fpulse * 3);
|
||||
digitalWrite(PIN_RF_TX_DATA, LOW);
|
||||
delayMicroseconds(fpulse * 1);
|
||||
digitalWrite(PIN_RF_TX_DATA, HIGH);
|
||||
delayMicroseconds(fpulse * 3);
|
||||
digitalWrite(PIN_RF_TX_DATA, LOW);
|
||||
delayMicroseconds(fpulse * 1);
|
||||
} else { // Write float
|
||||
digitalWrite(PIN_RF_TX_DATA, HIGH);
|
||||
delayMicroseconds(fpulse * 1);
|
||||
digitalWrite(PIN_RF_TX_DATA, LOW);
|
||||
delayMicroseconds(fpulse * 3);
|
||||
digitalWrite(PIN_RF_TX_DATA, HIGH);
|
||||
delayMicroseconds(fpulse * 3);
|
||||
digitalWrite(PIN_RF_TX_DATA, LOW);
|
||||
delayMicroseconds(fpulse * 1);
|
||||
}
|
||||
}
|
||||
// Send sync bit
|
||||
digitalWrite(PIN_RF_TX_DATA, HIGH);
|
||||
delayMicroseconds(fpulse * 1);
|
||||
digitalWrite(PIN_RF_TX_DATA, LOW); // and lower the signal
|
||||
delayMicroseconds(fpulse * 31);
|
||||
}
|
||||
delayMicroseconds(TRANSMITTER_STABLE_DELAY); // short delay to let the transmitter become stable (Note: Aurel RTX MID needs 500µS/0,5ms)
|
||||
digitalWrite(PIN_RF_TX_VCC,LOW); // Turn thew 433Mhz transmitter off
|
||||
digitalWrite(PIN_RF_RX_VCC,HIGH); // Turn the 433Mhz receiver on
|
||||
RFLinkHW();
|
||||
}
|
||||
#endif //PLUGIN_TX_003
|
|
@ -0,0 +1,341 @@
|
|||
//#######################################################################################################
|
||||
//## This Plugin is only for use with the RFLink software package ##
|
||||
//## Plugin-04: NewKAKU ##
|
||||
//#######################################################################################################
|
||||
/*********************************************************************************************\
|
||||
* This plugin takes care of receiving from and transmitting to "Klik-Aan-Klik-Uit" devices
|
||||
* working according to the learning code system. This protocol is also used by the Home Easy devices.
|
||||
* It includes direct DIM functionality.
|
||||
*
|
||||
* Author : StuntTeam
|
||||
* 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!
|
||||
***********************************************************************************************
|
||||
* Pulse (T) is 275us PDM
|
||||
* 0 = T,T,T,4T, 1 = T,4T,T,T, dim = T,T,T,T op bit 28
|
||||
*
|
||||
* From: Wieltje @ http://www.circuitsonline.net/forum/view/message/1181410#1181410
|
||||
* _ _
|
||||
* '0': | |_| |____ (T,T,T,3T)
|
||||
* _ _
|
||||
* '1': | |____| |_ (T,3T,T,T)
|
||||
* _ _
|
||||
* dim: | |_| |_ (T,T,T,T)
|
||||
*
|
||||
* T = korte periode = 275 µs (of 375, werkt ook)
|
||||
* lange periode = 3 of 4*T (werkt ook allebei)
|
||||
*
|
||||
* | 00100011110100100010011010 | 0 | 1 | 0000 |
|
||||
* | ID# | All | State | unit# |
|
||||
*
|
||||
* NewKAKU supports:
|
||||
* on/off ---- 000x Off/On
|
||||
* all on/off ---- 001x AllOff/AllOn
|
||||
* dim absolute xxxx 0110 Dim16 // dim on bit 27 + 4 extra bits for dim level
|
||||
*
|
||||
* NewKAKU bitstream= (First sent) AA AAAAAAAA AAAAAAAA AAAAAAAACCUUUU(LLLL) -> A=KAKU_address, C=command, U=KAKU-Unit, L=extra dimlevel bits (optional)
|
||||
*
|
||||
* Sample RF packet:
|
||||
* 20;B8;NewKaku;ID=00c142;SWITCH=1;CMD=OFF;
|
||||
* 20;B9;DEBUG;Pulses=132;Pulses(uSec)=200,2550,150,200,125,1200,150,200,150,1200,125,1200,150,225,125,1200,125,225,125,200,150,1200,150,200,150,1200,150,1200,125,200,125,200,125,1225,125,1200,125,225,150,200,150,1200,150,1200,150,200,150,1200,150,225,125,200,150,1200,125,200,150,1200,125,200,150,1200,150,200,125,1225,150,200,125,1200,150,1200,125,225,125,200,125,1200,150,1200,125,225,125,200,125,1225,125,200,125,1225,125,200,125,1200,125,200,150,1225,125,1200,150,200,125,200,125,1200,125,200,150,1200,125,200,125,1200,150,200,125,1200,125,200,125,1200,150,200,125,1200,150,200,150,1200,125;
|
||||
* 20;06;DEBUG;Pulses=132;Pulses(uSec)=175,2575,150,200,150,1200,150,200,150,1200,150,1200,150,200,125,1200,150,200,125,200,150,1200,125,200,150,1200,150,1200,150,200,150,200,150,1225,150,1200,125,225,150,200,125,1200,150,1200,150,200,150,1200,150,200,150,200,125,1225,125,200,150,1200,125,200,150,1200,125,200,150,1200,150,200,150,1200,150,1200,125,200,150,200,125,1200,150,1200,125,225,150,200,125,1200,150,200,150,1200,150,200,150,1200,150,200,150,1225,125,1200,150,200,125,200,150,1200,150,200,125,1200,150,200,150,1200,150,200,150,1200,150,200,125,1225,125,200,125,1200,150,200,150,1200,150
|
||||
\*********************************************************************************************/
|
||||
#define NewKAKU_RawSignalLength 132 // regular KAKU packet length
|
||||
#define NewKAKUdim_RawSignalLength 148 // KAKU packet length including DIM bits
|
||||
#define NewKAKU_mT 650/RAWSIGNAL_SAMPLE_RATE // us, approx. in between 1T and 4T
|
||||
|
||||
#ifdef PLUGIN_004
|
||||
boolean Plugin_004(byte function, char *string) {
|
||||
// nieuwe KAKU bestaat altijd uit start bit + 32 bits + evt 4 dim bits. Ongelijk, dan geen NewKAKU
|
||||
if ( (RawSignal.Number != NewKAKU_RawSignalLength) && (RawSignal.Number != NewKAKUdim_RawSignalLength) ) return false;
|
||||
if (RawSignal.Pulses[0]==15) return true; // Home Easy, skip KAKU
|
||||
boolean Bit;
|
||||
int i;
|
||||
//int P0,P1,P2,P3;
|
||||
byte P0,P1,P2,P3;
|
||||
byte dim=0;
|
||||
byte dimbitpresent=0;
|
||||
unsigned long bitstream=0L;
|
||||
|
||||
// RawSignal.Pulses[1] startbit with duration of 1T => ignore
|
||||
// RawSignal.Pulses[2] long space after startbit with duration of 8T => ignore
|
||||
i=3; // RawSignal.Pulses[3] is first pulse of a T,xT,T,xT combination
|
||||
do {
|
||||
P0=RawSignal.Pulses[i] ; // * RawSignal.Multiply;
|
||||
P1=RawSignal.Pulses[i+1]; // * RawSignal.Multiply;
|
||||
P2=RawSignal.Pulses[i+2]; // * RawSignal.Multiply;
|
||||
P3=RawSignal.Pulses[i+3]; // * RawSignal.Multiply;
|
||||
|
||||
if (P0<NewKAKU_mT && P1<NewKAKU_mT && P2<NewKAKU_mT && P3>NewKAKU_mT) {
|
||||
Bit=0; // T,T,T,4T
|
||||
} else
|
||||
if (P0<NewKAKU_mT && P1>NewKAKU_mT && P2<NewKAKU_mT && P3<NewKAKU_mT) {
|
||||
Bit=1; // T,4T,T,T
|
||||
} else
|
||||
if (P0<NewKAKU_mT && P1<NewKAKU_mT && P2<NewKAKU_mT && P3<NewKAKU_mT) { // T,T,T,T should be on i=111 (bit 28)
|
||||
dimbitpresent=1;
|
||||
if(RawSignal.Number!=NewKAKUdim_RawSignalLength) { // dim set but no dim bits present => invalid signal
|
||||
return false;
|
||||
}
|
||||
//if (i != 111) return false; // not the right location for the dim bit indicator
|
||||
} else {
|
||||
//Serial.println("Unknown pattern");
|
||||
return false; // Other pulse patterns are invalid within the AC KAKU signal.
|
||||
}
|
||||
if(i<130) { // all bits that belong to the 32-bit pulse sequence (32bits * 4 positions per bit + pulse/space for startbit)
|
||||
bitstream=(bitstream<<1) | Bit;
|
||||
} else { // remaining 4 bits that set the dim level
|
||||
dim=(dim<<1) | Bit;
|
||||
}
|
||||
i+=4; // Next 4 pulses
|
||||
} while(i<RawSignal.Number-2); //-2 to exclude the stopbit space/pulse
|
||||
//==================================================================================
|
||||
// Prevent repeating signals from showing up
|
||||
//==================================================================================
|
||||
if(SignalHash!=SignalHashPrevious || ((RepeatingTimer+700)<millis() ) || SignalCRC != bitstream ) { // 1000
|
||||
// not seen the RF packet recently
|
||||
//Serial.print("NKAKU PREV:");
|
||||
//Serial.println(SignalHashPrevious);
|
||||
//if ((SignalHashPrevious==14) && ((RepeatingTimer+2000)>millis()) ) {
|
||||
// SignalHash=14;
|
||||
// return true; // SignalHash 14 = HomeEasy, eg. cant switch KAKU after HE for 2 seconds
|
||||
//}
|
||||
if ((SignalHashPrevious==11) && ((RepeatingTimer+2000)>millis()) ) {
|
||||
SignalHash=11;
|
||||
return true; // SignalHash 11 = FA500, eg. cant switch KAKU after FA500 for 2 seconds
|
||||
}
|
||||
|
||||
SignalCRC=bitstream;
|
||||
} else {
|
||||
// already seen the RF packet recently
|
||||
//Serial.println("Skip");
|
||||
return true;
|
||||
}
|
||||
//==================================================================================
|
||||
// Output
|
||||
// ----------------------------------
|
||||
sprintf(pbuffer, "20;%02X;", PKSequenceNumber++); // Node and packet number
|
||||
Serial.print( pbuffer );
|
||||
// ----------------------------------
|
||||
Serial.print(F("NewKaku;")); // Label
|
||||
sprintf(pbuffer, "ID=%08lx;",((bitstream) >> 6) ); // ID
|
||||
Serial.print( pbuffer );
|
||||
sprintf(pbuffer, "SWITCH=%x;", ((bitstream)&0x0f)+1 );
|
||||
Serial.print( pbuffer );
|
||||
Serial.print(F("CMD="));
|
||||
int command = (bitstream >> 4) & 0x03;
|
||||
if (command > 1) command ++;
|
||||
if (i>140 && dimbitpresent==1) { // Command and Dim part
|
||||
sprintf(pbuffer, "SET_LEVEL=%d;", dim );
|
||||
Serial.print( pbuffer );
|
||||
} else {
|
||||
if ( command == 0 ) Serial.print(F("OFF;"));
|
||||
if ( command == 1 ) Serial.print(F("ON;"));
|
||||
if ( command == 3 ) Serial.print(F("ALLOFF;"));
|
||||
if ( command == 4 ) Serial.print(F("ALLON;"));
|
||||
}
|
||||
Serial.println();
|
||||
// ----------------------------------
|
||||
RawSignal.Repeats=true; // suppress repeats of the same RF packet
|
||||
RawSignal.Number=0;
|
||||
return true;
|
||||
}
|
||||
#endif // Plugin_004
|
||||
|
||||
#ifdef PLUGIN_TX_004
|
||||
void AC_Send(unsigned long data, byte cmd);
|
||||
|
||||
boolean PluginTX_004(byte function, char *string) {
|
||||
boolean success=false;
|
||||
//10;NewKaku;123456;3;ON; // ON, OFF, ALLON, ALLOFF, ALL 99, 99
|
||||
//10;NewKaku;0cac142;2;ON;
|
||||
//10;NewKaku;050515;f;OFF;
|
||||
//10;NewKaku;2100fed;1;ON;
|
||||
//10;NewKaku;000001;10;ON;
|
||||
//10;NewKaku;306070b;f;ON;
|
||||
//10;NewKaku;306070b;10;ON;
|
||||
//01234567890123456789012
|
||||
if (strncasecmp(InputBuffer_Serial+3,"NEWKAKU;",8) == 0) {
|
||||
byte x=18; // pointer to the switch number
|
||||
if (InputBuffer_Serial[17] != ';') {
|
||||
if (InputBuffer_Serial[18] != ';') {
|
||||
return false;
|
||||
} else {
|
||||
x=19;
|
||||
}
|
||||
}
|
||||
|
||||
unsigned long bitstream=0L;
|
||||
unsigned long tempaddress=0L;
|
||||
byte cmd=0;
|
||||
byte c=0;
|
||||
byte Address=0; // Address 1..16
|
||||
|
||||
// -----
|
||||
InputBuffer_Serial[ 9]=0x30; // Get NEWKAKU/AC main address part from hexadecimal value
|
||||
InputBuffer_Serial[10]=0x78;
|
||||
InputBuffer_Serial[x-1]=0x00;
|
||||
tempaddress=str2int(InputBuffer_Serial+9);
|
||||
// -----
|
||||
//while((c=InputBuffer_Serial[x++])!=';'){ // Address: 1 to 16
|
||||
// if(c>='0' && c<='9'){Address=Address*10;Address=Address+c-'0';}
|
||||
//}
|
||||
InputBuffer_Serial[x-2]=0x30; // Get unit number from hexadecimal value
|
||||
InputBuffer_Serial[x-1]=0x78; // x points to the first character of the unit number
|
||||
if (InputBuffer_Serial[x+1] == ';') {
|
||||
InputBuffer_Serial[x+1]=0x00;
|
||||
cmd=2;
|
||||
} else {
|
||||
if (InputBuffer_Serial[x+2] == ';') {
|
||||
InputBuffer_Serial[x+2]=0x00;
|
||||
cmd=3;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
Address=str2int(InputBuffer_Serial+(x-2)); // NewKAKU unit number
|
||||
if (Address > 16) return false; // invalid address
|
||||
Address--; // 1 to 16 -> 0 to 15 (transmitted value is 1 less than shown values)
|
||||
x=x+cmd; // point to on/off/dim command part
|
||||
// -----
|
||||
tempaddress=(tempaddress <<6) + Address; // Complete transmitted address
|
||||
// -----
|
||||
cmd=str2cmd(InputBuffer_Serial+x); // Get ON/OFF etc. command
|
||||
if (cmd == false) { // Not a valid command received? ON/OFF/ALLON/ALLOFF
|
||||
cmd=str2int(InputBuffer_Serial+x); // get DIM value
|
||||
}
|
||||
// --------------- Prepare bitstream ------------
|
||||
bitstream=tempaddress & 0xFFFFFFCF; // adres geheel over nemen behalve de twee bits 5 en 6 die het schakel commando bevatten.
|
||||
|
||||
// Dimming of groups is also possible but not supported yet!
|
||||
// when level=0 is it better to transmit just the off command ?
|
||||
|
||||
if (cmd == VALUE_ON || cmd == VALUE_OFF) {
|
||||
bitstream|=(cmd == VALUE_ON)<<4; // bit-5 is the on/off command in the KAKU signal
|
||||
cmd=0xff;
|
||||
} else
|
||||
if (cmd == VALUE_ALLON || cmd == VALUE_ALLOFF) {
|
||||
bitstream|= B1 << 5; // bit 5 is the group indicator
|
||||
bitstream|=(cmd == VALUE_ALLON)<<4; // bit-4 is the on/off indicator
|
||||
cmd=0xff;
|
||||
}
|
||||
// bitstream now contains the AC/NewKAKU-bits that have to be transmitted
|
||||
// --------------- NEWKAKU SEND ------------
|
||||
AC_Send(bitstream, cmd);
|
||||
success=true;
|
||||
}
|
||||
// --------------------------------------
|
||||
return success;
|
||||
}
|
||||
|
||||
void AC_Send(unsigned long data, byte cmd) {
|
||||
int fpulse = 260; // Pulse width in microseconds
|
||||
int fretrans = 10; // Number of code retransmissions
|
||||
|
||||
unsigned long bitstream = 0L;
|
||||
byte command;
|
||||
// prepare data to send
|
||||
for (unsigned short i=0; i<32; i++) { // reverse data bits
|
||||
bitstream<<=1;
|
||||
bitstream|=(data & B1);
|
||||
data>>=1;
|
||||
}
|
||||
if (cmd !=0xff) { // reverse dim bits
|
||||
for (unsigned short i=0; i<4; i++) {
|
||||
command<<=1;
|
||||
command|=(cmd & B1);
|
||||
cmd>>=1;
|
||||
}
|
||||
}
|
||||
// Prepare transmit
|
||||
digitalWrite(PIN_RF_RX_VCC,LOW); // Turn off power to the RF receiver
|
||||
digitalWrite(PIN_RF_TX_VCC,HIGH); // Enable the 433Mhz transmitter
|
||||
delayMicroseconds(TRANSMITTER_STABLE_DELAY); // short delay to let the transmitter become stable (Note: Aurel RTX MID needs 500µS/0,5ms)
|
||||
// send bits
|
||||
for (int nRepeat = 0; nRepeat <= fretrans; nRepeat++) {
|
||||
data=bitstream;
|
||||
if (cmd !=0xff) cmd=command;
|
||||
digitalWrite(PIN_RF_TX_DATA, HIGH);
|
||||
//delayMicroseconds(fpulse); //335
|
||||
delayMicroseconds(335);
|
||||
digitalWrite(PIN_RF_TX_DATA, LOW);
|
||||
delayMicroseconds(fpulse*10 + (fpulse >> 1)); //335*9=3015 //260*10=2600
|
||||
for (unsigned short i=0; i<32; i++) {
|
||||
if (i==27 && cmd !=0xff) { // DIM command, send special DIM sequence TTTT replacing on/off bit
|
||||
digitalWrite(PIN_RF_TX_DATA, HIGH);
|
||||
delayMicroseconds(fpulse);
|
||||
digitalWrite(PIN_RF_TX_DATA, LOW);
|
||||
delayMicroseconds(fpulse);
|
||||
digitalWrite(PIN_RF_TX_DATA, HIGH);
|
||||
delayMicroseconds(fpulse);
|
||||
digitalWrite(PIN_RF_TX_DATA, LOW);
|
||||
delayMicroseconds(fpulse);
|
||||
} else
|
||||
switch (data & B1) {
|
||||
case 0:
|
||||
digitalWrite(PIN_RF_TX_DATA, HIGH);
|
||||
delayMicroseconds(fpulse);
|
||||
digitalWrite(PIN_RF_TX_DATA, LOW);
|
||||
delayMicroseconds(fpulse);
|
||||
digitalWrite(PIN_RF_TX_DATA, HIGH);
|
||||
delayMicroseconds(fpulse);
|
||||
digitalWrite(PIN_RF_TX_DATA, LOW);
|
||||
delayMicroseconds(fpulse*5); // 335*3=1005 260*5=1300 260*4=1040
|
||||
break;
|
||||
case 1:
|
||||
digitalWrite(PIN_RF_TX_DATA, HIGH);
|
||||
delayMicroseconds(fpulse);
|
||||
digitalWrite(PIN_RF_TX_DATA, LOW);
|
||||
delayMicroseconds(fpulse*5);
|
||||
digitalWrite(PIN_RF_TX_DATA, HIGH);
|
||||
delayMicroseconds(fpulse);
|
||||
digitalWrite(PIN_RF_TX_DATA, LOW);
|
||||
delayMicroseconds(fpulse);
|
||||
break;
|
||||
}
|
||||
//Next bit
|
||||
data>>=1;
|
||||
}
|
||||
// send dim bits when needed
|
||||
if (cmd != 0xff) { // need to send DIM command bits
|
||||
for (unsigned short i=0; i<4; i++) { // 4 bits
|
||||
switch (cmd & B1) {
|
||||
case 0:
|
||||
digitalWrite(PIN_RF_TX_DATA, HIGH);
|
||||
delayMicroseconds(fpulse);
|
||||
digitalWrite(PIN_RF_TX_DATA, LOW);
|
||||
delayMicroseconds(fpulse);
|
||||
digitalWrite(PIN_RF_TX_DATA, HIGH);
|
||||
delayMicroseconds(fpulse);
|
||||
digitalWrite(PIN_RF_TX_DATA, LOW);
|
||||
delayMicroseconds(fpulse*5); // 335*3=1005 260*5=1300
|
||||
break;
|
||||
case 1:
|
||||
digitalWrite(PIN_RF_TX_DATA, HIGH);
|
||||
delayMicroseconds(fpulse);
|
||||
digitalWrite(PIN_RF_TX_DATA, LOW);
|
||||
delayMicroseconds(fpulse*5);
|
||||
digitalWrite(PIN_RF_TX_DATA, HIGH);
|
||||
delayMicroseconds(fpulse);
|
||||
digitalWrite(PIN_RF_TX_DATA, LOW);
|
||||
delayMicroseconds(fpulse);
|
||||
break;
|
||||
}
|
||||
//Next bit
|
||||
cmd>>=1;
|
||||
}
|
||||
}
|
||||
//Send termination/synchronisation-signal. Total length: 32 periods
|
||||
digitalWrite(PIN_RF_TX_DATA, HIGH);
|
||||
delayMicroseconds(fpulse);
|
||||
digitalWrite(PIN_RF_TX_DATA, LOW);
|
||||
delayMicroseconds(fpulse*40); //31*335=10385 40*260=10400
|
||||
}
|
||||
// End transmit
|
||||
delayMicroseconds(TRANSMITTER_STABLE_DELAY); // short delay to let the transmitter become stable (Note: Aurel RTX MID needs 500µS/0,5ms)
|
||||
digitalWrite(PIN_RF_TX_VCC,LOW); // Turn thew 433Mhz transmitter off
|
||||
digitalWrite(PIN_RF_RX_VCC,HIGH); // Turn the 433Mhz receiver on
|
||||
RFLinkHW();
|
||||
}
|
||||
#endif // Plugin_TX_004
|
|
@ -0,0 +1,204 @@
|
|||
//#######################################################################################################
|
||||
//## This Plugin is only for use with the RFLink software package ##
|
||||
//## Plugin-03: Intertek Eurodomest 972080 ##
|
||||
//#######################################################################################################
|
||||
/*********************************************************************************************\
|
||||
* This plugin takes care of sending and receiving the Intertek Eurodomest 972080 protocol.
|
||||
*
|
||||
* Author : StuntTeam
|
||||
* 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!
|
||||
***********************************************************************************************
|
||||
* Technical information:
|
||||
*
|
||||
* 0111 00011011 00011111 000 0
|
||||
* AAAA AAAAAAAA AAAAAAAA BBB C
|
||||
* 0000 00000011 10101010 101 1
|
||||
* 0000 00000011 10101010 111 0
|
||||
*
|
||||
* 0011 01101001 01101011 000 0 Eurodomest 1 on
|
||||
* 0011 01101001 01101011 000 1 Eurodomest 1 off
|
||||
* 0011 01101001 01101011 001 0 ED 2 on
|
||||
* 0011 01101001 01101011 001 1 ED 2 off
|
||||
* 0011 01101001 01101011 010 0 3 on
|
||||
* 0011 01101001 01101011 010 1 3 off
|
||||
* 0011 01101001 01101011 100 0 4 on
|
||||
* 0011 01101001 01101011 100 1 4 off
|
||||
* 0011 01101001 01101011 110 1 all on
|
||||
* 0011 01101001 01101011 111 0 all off
|
||||
*
|
||||
*
|
||||
* A = ID (20 bits)
|
||||
* B = UnitCode (3 bits)
|
||||
* C = switch code (ON/OFF) (1 bit)
|
||||
*
|
||||
* 20;2A;DEBUG;Pulses=50;Pulses(uSec)= 900,200,825,200,225,825,200,825,800,200,200,825,200,825,825,200,225,825,800,200,800,225,225,825,800,225,200,825,225,825,800,225,225,825,800,225,200,825,200,825,225,825,225,825,225,825,800,200,200;
|
||||
* 20;9D;DEBUG;Pulses=50;Pulses(uSec)=1250,200,750,175,200,750,200,750,750,200,200,750,200,750,750,200,200,750,750,200,750,200,200,750,750,200,200,750,200,750,750,200,200,750,750,200,200,750,200,750,750,200,750,200,750,200,750,200,200;
|
||||
\*********************************************************************************************/
|
||||
#define EURODOMEST_PulseLength 50
|
||||
|
||||
#define EURODOMEST_PULSEMID 400/RAWSIGNAL_SAMPLE_RATE
|
||||
#define EURODOMEST_PULSEMIN 100/RAWSIGNAL_SAMPLE_RATE
|
||||
#define EURODOMEST_PULSEMAX 900/RAWSIGNAL_SAMPLE_RATE
|
||||
|
||||
#ifdef PLUGIN_005
|
||||
boolean Plugin_005(byte function, char *string) {
|
||||
if (RawSignal.Number != EURODOMEST_PulseLength) return false;
|
||||
if (RawSignal.Pulses[0]==63) return false; // No need to test, packet for plugin 63
|
||||
unsigned long bitstream=0;
|
||||
byte unitcode=0;
|
||||
byte command=0;
|
||||
unsigned long address=0;
|
||||
// ==========================================================================
|
||||
if(RawSignal.Pulses[49] > EURODOMEST_PULSEMID) return false; // last pulse needs to be short, otherwise no Eurodomest protocol
|
||||
// get all 24 bits
|
||||
for(int x=2;x < EURODOMEST_PulseLength;x+=2) {
|
||||
if(RawSignal.Pulses[x] > EURODOMEST_PULSEMID) { // long pulse
|
||||
if (RawSignal.Pulses[x-1] > EURODOMEST_PULSEMID) return false; // not a 01 or 10 transmission
|
||||
if(RawSignal.Pulses[x] > EURODOMEST_PULSEMAX) return false; // make sure the long pulse is within range
|
||||
bitstream = (bitstream << 1) | 0x1;
|
||||
} else { // short pulse
|
||||
if (RawSignal.Pulses[x] < EURODOMEST_PULSEMIN) return false; // pulse too short to be Eurodomest
|
||||
if (RawSignal.Pulses[x-1] < EURODOMEST_PULSEMID) return false; // not a 01 or 10 transmission
|
||||
bitstream = (bitstream << 1);
|
||||
}
|
||||
}
|
||||
//==================================================================================
|
||||
// Prevent repeating signals from showing up
|
||||
//==================================================================================
|
||||
if(SignalHash!=SignalHashPrevious || RepeatingTimer<millis()) {
|
||||
// not seen the RF packet recently
|
||||
if (bitstream==0) return false; // no bits detected?
|
||||
} else {
|
||||
// already seen the RF packet recently
|
||||
return true;
|
||||
}
|
||||
//==================================================================================
|
||||
// perform sanity checks to prevent false positives
|
||||
//==================================================================================
|
||||
address=bitstream;
|
||||
address=(address >> 4) &0xfffff;
|
||||
if (address==0) return false; // Address would never be 0
|
||||
if (address==0xfffff) return false; // Address would never be FFFFF
|
||||
// ----------------------------------
|
||||
unitcode=(( bitstream >> 1)& 0x7);
|
||||
command=((bitstream) & 0x01);
|
||||
if (unitcode == 3) return false; // invalid button code?
|
||||
if (unitcode == 4) unitcode--;
|
||||
// if (unitcode == 5) return false; // Note: unitcode 5 is present on the PCB and working but not used on any remotes.
|
||||
if (unitcode > 7) return false; // invalid button code?
|
||||
//==================================================================================
|
||||
// Output
|
||||
// ----------------------------------
|
||||
sprintf(pbuffer, "20;%02X;", PKSequenceNumber++); // Node and packet number
|
||||
Serial.print( pbuffer );
|
||||
// ----------------------------------
|
||||
Serial.print(F("Eurodomest;")); // Label
|
||||
sprintf(pbuffer, "ID=%06lx;",(address)&0xffffff) ; // ID
|
||||
Serial.print( pbuffer );
|
||||
sprintf(pbuffer, "SWITCH=%02x;", unitcode); // ID
|
||||
Serial.print( pbuffer );
|
||||
Serial.print(F("CMD="));
|
||||
if ( unitcode > 4) {
|
||||
Serial.print(F("ALL"));
|
||||
if ( command == 0) {
|
||||
Serial.print(F("OFF;"));
|
||||
} else {
|
||||
Serial.print(F("ON;"));
|
||||
}
|
||||
} else {
|
||||
if ( command == 1) {
|
||||
Serial.print(F("OFF;"));
|
||||
} else {
|
||||
Serial.print(F("ON;"));
|
||||
}
|
||||
}
|
||||
Serial.println();
|
||||
// ----------------------------------
|
||||
RawSignal.Repeats=true; // suppress repeats of the same RF packet
|
||||
RawSignal.Number=0;
|
||||
return true;
|
||||
}
|
||||
#endif //PLUGIN_005
|
||||
|
||||
#ifdef PLUGIN_TX_005
|
||||
void Eurodomest_Send(unsigned long address);
|
||||
|
||||
boolean PluginTX_005(byte function, char *string) {
|
||||
//10;EURODOMEST;03696b;0;ON;
|
||||
//012345678901234567890123456
|
||||
boolean success=false;
|
||||
if (strncasecmp(InputBuffer_Serial+3,"EURODOMEST;",11) == 0) { // KAKU Command eg.
|
||||
unsigned long bitstream=0L;
|
||||
if (InputBuffer_Serial[20] != ';') return success;
|
||||
if (InputBuffer_Serial[22] != ';') return success;
|
||||
|
||||
InputBuffer_Serial[12]=0x30;
|
||||
InputBuffer_Serial[13]=0x78;
|
||||
InputBuffer_Serial[20]=0x00;
|
||||
bitstream=str2int(InputBuffer_Serial+12);// Address
|
||||
InputBuffer_Serial[22]=0x00;
|
||||
byte temp=str2int(InputBuffer_Serial+21);// Button number
|
||||
bitstream=(bitstream) << 4;
|
||||
if (temp == 1) bitstream=bitstream+0x02; // 0010
|
||||
if (temp == 2) bitstream=bitstream+0x04; // 0100
|
||||
if (temp == 3) bitstream=bitstream+0x08; // 1000
|
||||
if (temp == 6) bitstream=bitstream+0x0d; // 1101
|
||||
if (temp == 7) bitstream=bitstream+0x0f; // 1111
|
||||
if (temp > 7) {
|
||||
return success;
|
||||
}
|
||||
byte command=0;
|
||||
command = str2cmd(InputBuffer_Serial+23);
|
||||
if (command == VALUE_OFF) {
|
||||
bitstream=bitstream|1;
|
||||
}
|
||||
Eurodomest_Send(bitstream); // the full bitstream to send
|
||||
success=true;
|
||||
}
|
||||
return success;
|
||||
}
|
||||
|
||||
void Eurodomest_Send(unsigned long address) {
|
||||
int fpulse = 296; // Pulse witdh in microseconds
|
||||
int fretrans = 7; // Number of code retransmissions
|
||||
uint32_t fdatabit;
|
||||
uint32_t fdatamask = 0x800000;
|
||||
uint32_t fsendbuff;
|
||||
|
||||
digitalWrite(PIN_RF_RX_VCC,LOW); // Turn off power to the RF receiver
|
||||
digitalWrite(PIN_RF_TX_VCC,HIGH); // Enable the 433Mhz transmitter
|
||||
delayMicroseconds(TRANSMITTER_STABLE_DELAY); // short delay to let the transmitter become stable (Note: Aurel RTX MID needs 500µS/0,5ms)
|
||||
|
||||
for (int nRepeat = 0; nRepeat <= fretrans; nRepeat++) {
|
||||
fsendbuff=address;
|
||||
// Send command
|
||||
for (int i = 0; i < 24; i++) { // Eurodomest packet is 24 bits
|
||||
// read data bit
|
||||
fdatabit = fsendbuff & fdatamask; // Get most left bit
|
||||
fsendbuff = (fsendbuff << 1); // Shift left
|
||||
|
||||
if (fdatabit != fdatamask) { // Write 0
|
||||
digitalWrite(PIN_RF_TX_DATA, HIGH);
|
||||
delayMicroseconds(fpulse * 3);
|
||||
digitalWrite(PIN_RF_TX_DATA, LOW);
|
||||
delayMicroseconds(fpulse * 1);
|
||||
} else { // Write 1
|
||||
digitalWrite(PIN_RF_TX_DATA, HIGH);
|
||||
delayMicroseconds(fpulse * 1);
|
||||
digitalWrite(PIN_RF_TX_DATA, LOW);
|
||||
delayMicroseconds(fpulse * 3);
|
||||
}
|
||||
}
|
||||
digitalWrite(PIN_RF_TX_DATA, HIGH);
|
||||
delayMicroseconds(fpulse * 1);
|
||||
digitalWrite(PIN_RF_TX_DATA, LOW); // and lower the signal
|
||||
delayMicroseconds(fpulse * 32);
|
||||
}
|
||||
delayMicroseconds(TRANSMITTER_STABLE_DELAY); // short delay to let the transmitter become stable (Note: Aurel RTX MID needs 500µS/0,5ms)
|
||||
digitalWrite(PIN_RF_TX_VCC,LOW); // Turn the 433Mhz transmitter off
|
||||
digitalWrite(PIN_RF_RX_VCC,HIGH); // Turn the 433Mhz receiver on
|
||||
RFLinkHW();
|
||||
}
|
||||
#endif //PLUGIN_TX_005
|
|
@ -0,0 +1,287 @@
|
|||
//#######################################################################################################
|
||||
//## This Plugin is only for use with the RFLink software package ##
|
||||
//## Plugin-006 Blyss & Avidsen ##
|
||||
//#######################################################################################################
|
||||
/*********************************************************************************************\
|
||||
* This Plugin takes care of receiving of the Blyss protocol
|
||||
*
|
||||
* Author : StuntTeam
|
||||
* 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!
|
||||
*********************************************************************************************
|
||||
* Changelog: v1.0 initial release
|
||||
*********************************************************************************************
|
||||
* Technical information:
|
||||
* RF packets contain 106 pulses, 52 bits
|
||||
*
|
||||
* BLYSS Message Format:
|
||||
* AAAAAAAA BBBBCCCC CCCCCCCC CCCCDDDD | EEEEFFFF FFFFGGGG GGGG
|
||||
*
|
||||
* A = Preamble, always 0xFE (0x32 in case of Avidsen)
|
||||
* B = Global Channel (A=0,B=1,C=2,D=3)
|
||||
* C = Address
|
||||
* D = sub channel (channel 1=8, 2=4, 3=2, 4=1, 5=3) all channels = 0
|
||||
* E = Light Status
|
||||
* F = Rolling Code (0x98 -> 0xDA -> 0x1E -> 0xE6 -> 0x67)
|
||||
* G = Time Stamp (random value?)
|
||||
*
|
||||
* Details https://skyduino.wordpress.com/2012/07/19/hack-partie-2-reverse-engineering-des-interrupteurs-domotique-blyss/
|
||||
* https://barbudor.wiki.zoho.com/Système-domotique-Blyss-de-Castorama.html
|
||||
*
|
||||
* BlyssSend address,switch,cmd; => (16 bits,8 bits,on/off/allon/alloff)
|
||||
* 20;0B;DEBUG;Pulses=106;Pulses(uSec)=2160,450,570,420,600,420,600,450,570,420,600,420,600,450,570,810,210,870,150,840,180,840,180,840,180,420,600,420,600,420,600,450,570,420,600,420,600,420,600,420,600,420,600,840,180,840,210,450,570,450,600,810,180,840,180,840,180,420,600,810,210,840,180,810,210,810,210,870,180,810,210,450,570,450,570,840,180,840,210,450,570,420,600,840,180,810,210,840,180,840,210,840,180,840,180,810,210,840,210,420,600,810,210,420,600,6990;
|
||||
* 20;0C;Blyss;ID=ff98;SWITCH=A1;CMD=OFF;
|
||||
\*********************************************************************************************/
|
||||
#define BLYSS_PULSECOUNT 106
|
||||
#define BLYSS_PULSEMID 500/RAWSIGNAL_SAMPLE_RATE
|
||||
|
||||
#ifdef PLUGIN_006
|
||||
boolean Plugin_006(byte function, char *string) {
|
||||
if (RawSignal.Number != BLYSS_PULSECOUNT) return false;
|
||||
unsigned long bitstream=0L;
|
||||
unsigned long bitstream1=0L;
|
||||
byte bitcounter=0;
|
||||
byte checksum=0;
|
||||
int type=0;
|
||||
//==================================================================================
|
||||
// get bits
|
||||
for(byte x=2;x < BLYSS_PULSECOUNT;x=x+2) {
|
||||
if (RawSignal.Pulses[x] > BLYSS_PULSEMID) {
|
||||
if (bitcounter < 32) {
|
||||
bitstream = (bitstream << 1);
|
||||
} else {
|
||||
bitstream1 = (bitstream1 << 1);
|
||||
}
|
||||
bitcounter++;
|
||||
} else {
|
||||
if (bitcounter < 32) {
|
||||
bitstream = (bitstream << 1) | 0x1;
|
||||
} else {
|
||||
bitstream1 = (bitstream1 << 1) | 0x1;
|
||||
}
|
||||
bitcounter++;
|
||||
}
|
||||
}
|
||||
//==================================================================================
|
||||
// all bits received, make sure checksum is okay
|
||||
//==================================================================================
|
||||
checksum=((bitstream) >> 24); // test preamble
|
||||
if ((checksum != 0xFE) && (checksum != 0x32) ) return false; // must be 0xFE/32
|
||||
if (checksum == 0x32) type=1;
|
||||
//==================================================================================
|
||||
// Prevent repeating signals from showing up
|
||||
//==================================================================================
|
||||
if(SignalHash!=SignalHashPrevious || RepeatingTimer<millis()) {
|
||||
// not seen the RF packet recently
|
||||
} else {
|
||||
// already seen the RF packet recently
|
||||
return true;
|
||||
}
|
||||
//==================================================================================
|
||||
byte status=((bitstream1) >> 16) &0x0f;
|
||||
if (status > 3) return false;
|
||||
byte channel=((bitstream) >> 20) &0x0f;
|
||||
unsigned int address=((bitstream) >> 4) &0xffff;
|
||||
byte subchan=(bitstream) &0xf;
|
||||
channel=channel+0x41;
|
||||
if (subchan==8) {
|
||||
subchan=1;
|
||||
} else
|
||||
if (subchan==4) {
|
||||
subchan=2;
|
||||
} else
|
||||
if (subchan==2) {
|
||||
subchan=3;
|
||||
} else
|
||||
if (subchan==1) {
|
||||
subchan=4;
|
||||
} else
|
||||
if (subchan==3) {
|
||||
subchan=5;
|
||||
}
|
||||
//==================================================================================
|
||||
// Output
|
||||
// ----------------------------------
|
||||
sprintf(pbuffer, "20;%02X;", PKSequenceNumber++);// Node and packet number
|
||||
Serial.print( pbuffer );
|
||||
// ----------------------------------
|
||||
if (type == 0) {
|
||||
Serial.print(F("Blyss;")); // Label
|
||||
} else {
|
||||
Serial.print(F("Avidsen;")); // Label
|
||||
}
|
||||
sprintf(pbuffer, "ID=%04x;", address); // ID
|
||||
Serial.print( pbuffer );
|
||||
sprintf(pbuffer, "SWITCH=%c%d;", channel,subchan);
|
||||
Serial.print( pbuffer );
|
||||
Serial.print(F("CMD=")); // command
|
||||
if (status==0) Serial.print(F("ON;"));
|
||||
if (status==1) Serial.print(F("OFF;"));
|
||||
if (status==2) Serial.print(F("ALLON;"));
|
||||
if (status==3) Serial.print(F("ALLOFF;"));
|
||||
Serial.println();
|
||||
//==================================================================================
|
||||
RawSignal.Repeats=true; // suppress repeats of the same RF packet
|
||||
RawSignal.Number=0;
|
||||
return true;
|
||||
}
|
||||
#endif // PLUGIN_006
|
||||
|
||||
#ifdef PLUGIN_TX_006
|
||||
void Blyss_Send(unsigned long address, byte devtype);
|
||||
|
||||
boolean PluginTX_006(byte function, char *string) {
|
||||
boolean success=false;
|
||||
//10;Avidsen;00ff98;A1;OFF;
|
||||
//012345678901234567890123456
|
||||
//10;Blyss;00ff98;A1;OFF;
|
||||
//012345678901234567890123456
|
||||
int offset=0;
|
||||
if (strncasecmp(InputBuffer_Serial+3,"AVIDSEN;",8) == 0) { // Blyss Command eg.
|
||||
offset=2;
|
||||
}
|
||||
if ((strncasecmp(InputBuffer_Serial+3,"BLYSS;",6) == 0) || (offset==2)) { // Blyss Command eg.
|
||||
unsigned long Bitstream = 0L;
|
||||
if (InputBuffer_Serial[15+offset] != ';') return success; // check
|
||||
if (InputBuffer_Serial[18+offset] != ';') return success; // check
|
||||
|
||||
unsigned long Home=0; // Blyss channel A..P
|
||||
byte Address=0; // Blyss subchannel 1..5
|
||||
byte c;
|
||||
byte subchan=0; // subchannel
|
||||
|
||||
InputBuffer_Serial[7+offset]=0x30;
|
||||
InputBuffer_Serial[8+offset]=0x78;
|
||||
InputBuffer_Serial[15+offset]=0;
|
||||
Bitstream=str2int(InputBuffer_Serial+7+offset); // get address
|
||||
|
||||
c=tolower(InputBuffer_Serial[16+offset]); // A..P
|
||||
if(c>='a' && c<='p'){Home=c-'a';}
|
||||
c=tolower(InputBuffer_Serial[17+offset]); // 1..5
|
||||
if(c>='1' && c<='5'){Address=Address+c-'0';}
|
||||
|
||||
if (Address==1) subchan=0x80;
|
||||
if (Address==2) subchan=0x40;
|
||||
if (Address==3) subchan=0x20;
|
||||
if (Address==4) subchan=0x10;
|
||||
if (Address==5) subchan=0x30;
|
||||
|
||||
Home = Home << 24;
|
||||
Bitstream=(Bitstream) << 8;
|
||||
Bitstream=Bitstream+subchan;
|
||||
Bitstream=Bitstream+Home;
|
||||
|
||||
c = str2cmd(InputBuffer_Serial+19+offset); // ALL ON/OFF command
|
||||
if (c == VALUE_OFF) {
|
||||
Bitstream=Bitstream|1;
|
||||
} else {
|
||||
if (c == VALUE_ALLOFF) {
|
||||
Bitstream=Bitstream|3;
|
||||
} else
|
||||
if (c == VALUE_ALLON) {
|
||||
Bitstream=Bitstream|2;
|
||||
}
|
||||
}
|
||||
Blyss_Send(Bitstream, offset); // Bitstream contains the middle part of the bitstream to send
|
||||
success=true;
|
||||
}
|
||||
return success;
|
||||
}
|
||||
|
||||
void Blyss_Send(unsigned long address, byte devtype) {
|
||||
int fpulse = 400; // Pulse witdh in microseconds
|
||||
int fretrans = 8; // Number of code retransmissions
|
||||
uint32_t fdatabit;
|
||||
uint32_t fdatamask = 0x800000;
|
||||
uint32_t fsendbuff;
|
||||
unsigned char RollingCode[] = { 0x98, 0xDA, 0x1E, 0xE6, 0x67, 0x98};
|
||||
|
||||
digitalWrite(PIN_RF_RX_VCC,LOW); // Power off the RF receiver
|
||||
digitalWrite(PIN_RF_TX_VCC,HIGH); // Turn on the RF transmitter
|
||||
delayMicroseconds(TRANSMITTER_STABLE_DELAY); // short delay to let the transmitter become stable (Note: Aurel RTX MID needs 500µS/0,5ms)
|
||||
byte temp=(millis() &0xff); // used for the timestamp at the end of the RF packet
|
||||
for (int nRepeat = 0; nRepeat <= fretrans; nRepeat++) {
|
||||
// send SYNC 1P low, 6P high
|
||||
digitalWrite(PIN_RF_TX_DATA, LOW);
|
||||
delayMicroseconds(fpulse);
|
||||
digitalWrite(PIN_RF_TX_DATA, HIGH);
|
||||
delayMicroseconds(fpulse * 6);
|
||||
// end send SYNC
|
||||
// --------------
|
||||
// Send preamble (0xfe) - 8 bits
|
||||
if (devtype == 0) {
|
||||
fsendbuff=0x32;
|
||||
} else {
|
||||
fsendbuff=0xfe;
|
||||
}
|
||||
fdatamask=0x80;
|
||||
for (int i = 0; i < 8; i++) { // Preamble
|
||||
// read data bit
|
||||
fdatabit = fsendbuff & fdatamask; // Get most left bit
|
||||
fsendbuff = (fsendbuff << 1); // Shift left
|
||||
if (fdatabit != fdatamask) { // Write 0
|
||||
digitalWrite(PIN_RF_TX_DATA, LOW);
|
||||
delayMicroseconds(fpulse * 2);
|
||||
digitalWrite(PIN_RF_TX_DATA, HIGH);
|
||||
delayMicroseconds(fpulse * 1);
|
||||
} else { // Write 1
|
||||
digitalWrite(PIN_RF_TX_DATA, LOW);
|
||||
delayMicroseconds(fpulse * 1);
|
||||
digitalWrite(PIN_RF_TX_DATA, HIGH);
|
||||
delayMicroseconds(fpulse * 2);
|
||||
}
|
||||
}
|
||||
// --------------
|
||||
fsendbuff=address;
|
||||
fdatamask=0x8000000;
|
||||
// Send command (channel/address/status) - 28 bits
|
||||
for (int i = 0; i < 28; i++) {
|
||||
// read data bit
|
||||
fdatabit = fsendbuff & fdatamask; // Get most left bit
|
||||
fsendbuff = (fsendbuff << 1); // Shift left
|
||||
if (fdatabit != fdatamask) { // Write 0
|
||||
digitalWrite(PIN_RF_TX_DATA, LOW);
|
||||
delayMicroseconds(fpulse * 2);
|
||||
digitalWrite(PIN_RF_TX_DATA, HIGH);
|
||||
delayMicroseconds(fpulse * 1);
|
||||
} else { // Write 1
|
||||
digitalWrite(PIN_RF_TX_DATA, LOW);
|
||||
delayMicroseconds(fpulse * 1);
|
||||
digitalWrite(PIN_RF_TX_DATA, HIGH);
|
||||
delayMicroseconds(fpulse * 2);
|
||||
}
|
||||
}
|
||||
// --------------
|
||||
// Send rolling code & timestamp - 16 bits
|
||||
fsendbuff=RollingCode[nRepeat];
|
||||
fsendbuff=(fsendbuff<<8)+temp;
|
||||
//fsendbuff=0x9800 + temp;
|
||||
fdatamask=0x8000;
|
||||
for (int i = 0; i < 16; i++) {
|
||||
// read data bit
|
||||
fdatabit = fsendbuff & fdatamask; // Get most left bit
|
||||
fsendbuff = (fsendbuff << 1); // Shift left
|
||||
if (fdatabit != fdatamask) { // Write 0
|
||||
digitalWrite(PIN_RF_TX_DATA, LOW);
|
||||
delayMicroseconds(fpulse * 2);
|
||||
digitalWrite(PIN_RF_TX_DATA, HIGH);
|
||||
delayMicroseconds(fpulse * 1);
|
||||
} else { // Write 1
|
||||
digitalWrite(PIN_RF_TX_DATA, LOW);
|
||||
delayMicroseconds(fpulse * 1);
|
||||
digitalWrite(PIN_RF_TX_DATA, HIGH);
|
||||
delayMicroseconds(fpulse * 2);
|
||||
}
|
||||
}
|
||||
// --------------
|
||||
digitalWrite(PIN_RF_TX_DATA, LOW);
|
||||
//delayMicroseconds(fpulse * 18); // delay between RF retransmits
|
||||
delay(24); // delay 23.8 ms
|
||||
}
|
||||
delayMicroseconds(TRANSMITTER_STABLE_DELAY); // short delay to let the transmitter become stable (Note: Aurel RTX MID needs 500µS/0,5ms)
|
||||
digitalWrite(PIN_RF_TX_VCC,LOW); // turn off the RF transmitter
|
||||
digitalWrite(PIN_RF_RX_VCC,HIGH); // power on the RF receiver
|
||||
RFLinkHW();
|
||||
}
|
||||
#endif // PLUGIN_TX_006
|
|
@ -0,0 +1,320 @@
|
|||
//#######################################################################################################
|
||||
//## This Plugin is only for use with the RFLink software package ##
|
||||
//## Plugin-007 CONRAD RSL2 ##
|
||||
//#######################################################################################################
|
||||
/*********************************************************************************************\
|
||||
* This Plugin takes care of receiving of the Conrad RSL2 protocol
|
||||
*
|
||||
* Author : StuntTeam
|
||||
* 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!
|
||||
*********************************************************************************************
|
||||
* Changelog: v1.0 initial release
|
||||
*********************************************************************************************
|
||||
* Technical information:
|
||||
* RF packets contain 66 pulses, 32 bits
|
||||
*
|
||||
* Conrad RSL2 Message Format:
|
||||
* AABBCDDD EEEEEEEE EEEEEEEE EEEEEEEE
|
||||
*
|
||||
* A = always 10
|
||||
* B = Button code
|
||||
* C = on/off command (inverted for some buttons/groups)
|
||||
* D = group code
|
||||
* E = 24 bit address
|
||||
*
|
||||
* Details: http://www.mikrocontroller.net/topic/252895
|
||||
*
|
||||
* ConradSend address,switch,cmd; => (16 bits,8 bits,on/off/allon/alloff)
|
||||
|
||||
20;5B;DEBUG;Pulses=66;Pulses(uSec)=400,1200,350,1200,350,1200,350,1200,350,1225,350,1200,350,1200,350,1200,350,1200,350,1200,350,1200,350,1200,350,1200,350,1225,350,1200,350,1200,1200,350,350,1225,350,1200,1200,350,350,1200,350,1200,1200,350,350,1200,350,1200,350,1200,350,1200,350,1200,350,1200,350,1200,350,1200,350,1200,350;
|
||||
|
||||
400,1200,350,1200,350,1200,350,1200,350,1225,350,1200,350,1200,350,1200,350,1200,350,1200,
|
||||
350,1200,350,1200,350,1200,350,1225,350,1200,350,1200,1200,350,350,1225,350,1200,1200,350,
|
||||
350,1200,350,1200,1200,350,350,1200,350,1200,350,1200,350,1200,350,1200,350,1200,350,1200,
|
||||
350,1200,350,1200,350;
|
||||
|
||||
20;3D;DEBUG;Pulses=68;Pulses(uSec)=600,6450,1290,330,390,1260,390,1260,360,1260,360,1260,390,1260,390,1260,1290,360,1260,360,1290,360,1290,330,1290,360,1260,360,1260,360,1290,330,1290,360,360,1260,360,1260,390,1260,390,1260,360,1260,1290,360,1260,360,360,1260,390,1260,360,1260,360,1260,360,1260,390,1260,1290,360,1290,360,1260,360,390,6990;
|
||||
20;3E;DEBUG;Pulses=68;Pulses(uSec)=720,6450,1290,330,390,1260,360,1260,360,1260,390,1260,390,1260,360,1260,1260,360,1290,330,1290,330,1290,360,1260,360,1260,360,1290,330,1290,360,1290,360,360,1260,360,1260,390,1260,360,1260,360,1260,1260,360,1290,330,390,1260,360,1260,360,1260,360,1260,390,1260,390,1260,1260,360,1260,360,1290,330,390,6990;
|
||||
20;3F;DEBUG;Pulses=68;Pulses(uSec)=630,6450,1290,360,360,1260,360,1260,390,1260,390,1260,360,1260,360,1260,1290,330,1290,330,1290,360,1260,360,1290,330,1290,330,1290,360,1260,360,1260,360,390,1260,390,1260,360,1260,360,1260,360,1260,1290,330,1290,360,360,1260,360,1260,390,1260,390,1260,360,1260,360,1260,1290,330,1290,330,1290,360,360,6990;
|
||||
|
||||
\*********************************************************************************************/
|
||||
#define CONRADRSL2_PULSECOUNT 66
|
||||
#define CONRADRSL2_PULSEMID 600/RAWSIGNAL_SAMPLE_RATE
|
||||
|
||||
#ifdef PLUGIN_007
|
||||
boolean Plugin_007(byte function, char *string){
|
||||
if ((RawSignal.Number != CONRADRSL2_PULSECOUNT) && (RawSignal.Number != CONRADRSL2_PULSECOUNT+2) ) return false;
|
||||
unsigned long bitstream=0L;
|
||||
byte checksum=0;
|
||||
byte button=0;
|
||||
byte group=0;
|
||||
byte action=0;
|
||||
byte start=0;
|
||||
if (RawSignal.Number == CONRADRSL2_PULSECOUNT+2) {
|
||||
start=2;
|
||||
}
|
||||
//==================================================================================
|
||||
// get bits
|
||||
for(byte x=1+start;x < RawSignal.Number-2;x=x+2) {
|
||||
if (RawSignal.Pulses[x] > CONRADRSL2_PULSEMID) {
|
||||
if (RawSignal.Pulses[x+1] > CONRADRSL2_PULSEMID) return false; // manchester check
|
||||
bitstream = (bitstream << 1) | 0x1; // 1
|
||||
} else {
|
||||
if (RawSignal.Pulses[x+1] < CONRADRSL2_PULSEMID) return false; // manchester check
|
||||
bitstream = (bitstream << 1); // 0
|
||||
}
|
||||
}
|
||||
//==================================================================================
|
||||
// Prevent repeating signals from showing up
|
||||
//==================================================================================
|
||||
if(SignalHash!=SignalHashPrevious || RepeatingTimer<millis()) {
|
||||
// not seen the RF packet recently
|
||||
if (bitstream == 0) return false; // sanity check
|
||||
} else {
|
||||
// already seen the RF packet recently
|
||||
return true;
|
||||
}
|
||||
//==================================================================================
|
||||
// all bits received, make sure checksum is okay
|
||||
//==================================================================================
|
||||
checksum=(((bitstream) >> 30)&0x0f); // first two bits should always be '10'
|
||||
if (checksum != 2) return false;
|
||||
//==================================================================================
|
||||
button=(((bitstream) >> 24)&0xff); // 10100011
|
||||
// ----- check for possible valid values
|
||||
if (button < 0x81) return false;
|
||||
if (button > 0xbe) return false;
|
||||
byte temp=(button)&0xf;
|
||||
if (temp == 0x07 || temp == 0x0b || temp == 0x0f ) return false;
|
||||
if (button == 0x83 || button == 0x86 || button == 0x89 || button == 0x8c || button == 0x91 ) return false;
|
||||
if (button == 0x94 || button == 0x9a || button == 0x9d || button == 0xa1 || button == 0xa4 ) return false;
|
||||
if (button == 0xaa || button == 0xad || button == 0xb1 || button == 0xb3 || button == 0xb4 ) return false;
|
||||
if (button == 0xba || button == 0xbd ) return false;
|
||||
// -----
|
||||
group=(button) & 0x7; // -- 111
|
||||
action=((button) >> 3) & 0x1; // -- a
|
||||
button = ((button) >> 4) & 0x3; // --bb
|
||||
// -----
|
||||
if (group == 3) {
|
||||
action=button;
|
||||
button=0;
|
||||
} else {
|
||||
if (button==3) {
|
||||
if (group == 6) { // toggle command bit
|
||||
button=0;
|
||||
action=(~action)&1;
|
||||
}
|
||||
if (group == 1 || group == 5) { // no toggle
|
||||
button=4;
|
||||
}
|
||||
if (group == 0) {
|
||||
action=(~action)&1; // toggle command bit
|
||||
button=8;
|
||||
}
|
||||
if (group == 2 || group == 4) { // no toggle
|
||||
button=12;
|
||||
}
|
||||
} else
|
||||
if (button==0) {
|
||||
if (group == 6 || group == 1) { // no toggle
|
||||
button=1;
|
||||
}
|
||||
if (group == 5) { // toggle command bit
|
||||
button=5;
|
||||
action=(~action)&1;
|
||||
}
|
||||
if (group == 0 || group == 4) { // no toggle
|
||||
button=9;
|
||||
}
|
||||
if (group == 2) { // toggle command bit
|
||||
button=13;
|
||||
action=(~action)&1;
|
||||
}
|
||||
} else
|
||||
if (button==2) {
|
||||
if (group == 6) { // toggle command bit
|
||||
button=2;
|
||||
action=(~action)&1;
|
||||
}
|
||||
if (group == 1 || group == 5) button=6; //
|
||||
|
||||
if (group == 0) { // toggle command bit
|
||||
button=10;
|
||||
action=(~action)&1;
|
||||
}
|
||||
|
||||
if (group == 2 || group == 4) { // no toggle
|
||||
button=14;
|
||||
//action=(~action)&1;
|
||||
}
|
||||
} else
|
||||
if (button==1) {
|
||||
if (group == 6) { // toggle command bit
|
||||
button=3;
|
||||
action=(~action)&1;
|
||||
}
|
||||
if (group == 1 || group == 5) { // no toggle
|
||||
button=7;
|
||||
//action=(~action)&1;
|
||||
}
|
||||
if (group == 0) { // toggle command bit
|
||||
button=11;
|
||||
action=(~action)&1;
|
||||
}
|
||||
if (group == 2 || group == 4) { // no toggle
|
||||
button=15;
|
||||
//action=(~action)&1;
|
||||
}
|
||||
}
|
||||
}
|
||||
//==================================================================================
|
||||
// Output
|
||||
// ----------------------------------
|
||||
sprintf(pbuffer, "20;%02X;", PKSequenceNumber++);// Node and packet number
|
||||
Serial.print( pbuffer );
|
||||
// ----------------------------------
|
||||
Serial.print(F("Conrad;")); // Label
|
||||
sprintf(pbuffer, "ID=%06lx;",((bitstream) &0xffffff) ); // ID
|
||||
Serial.print( pbuffer );
|
||||
sprintf(pbuffer, "SWITCH=%02x;", button); // Button number
|
||||
Serial.print( pbuffer );
|
||||
Serial.print(F("CMD=")); // command
|
||||
if (group==3) {
|
||||
Serial.print(F("ALL"));
|
||||
}
|
||||
if (action==1) {
|
||||
Serial.print(F("ON;"));
|
||||
} else { // 0 normal off, 2 group off
|
||||
Serial.print(F("OFF;"));
|
||||
}
|
||||
Serial.println();
|
||||
//==================================================================================
|
||||
RawSignal.Repeats=true; // suppress repeats of the same RF packet
|
||||
RawSignal.Number=0;
|
||||
return true;
|
||||
}
|
||||
#endif // PLUGIN_007
|
||||
|
||||
#ifdef PLUGIN_TX_007
|
||||
void RSL2_Send(unsigned long address);
|
||||
|
||||
boolean PluginTX_007(byte function, char *string) {
|
||||
boolean success=false;
|
||||
//10;CONRAD;000fa0;0;OFF;
|
||||
//10;CONRAD;009200;1;ON;
|
||||
//10;CONRAD;ff0607;1;OFF;
|
||||
//012345678901234567890123
|
||||
if (strncasecmp(InputBuffer_Serial+3,"CONRAD;",7) == 0) { // KAKU Command eg.
|
||||
unsigned long bitstream=0L;
|
||||
unsigned long command=0L;
|
||||
if (InputBuffer_Serial[16] != ';') return success;
|
||||
InputBuffer_Serial[8]=0x30;
|
||||
InputBuffer_Serial[9]=0x78;
|
||||
InputBuffer_Serial[16]=0;
|
||||
bitstream=str2int(InputBuffer_Serial+8); // Address
|
||||
|
||||
byte temp=str2int(InputBuffer_Serial+17); // het button/unit number (0x00..0x0f)
|
||||
if (temp < 16) { // No button with a number higher than 15
|
||||
byte cmd=str2cmd(InputBuffer_Serial+19); // ON/OFF
|
||||
if (cmd==VALUE_OFF) {
|
||||
if (temp == 0) command=0xbe;
|
||||
if (temp == 1) command=0x81;
|
||||
if (temp == 2) command=0xae;
|
||||
if (temp == 3) command=0x9e;
|
||||
if (temp == 4) command=0xb5;
|
||||
if (temp == 5) command=0x8d;
|
||||
if (temp == 6) command=0xa5;
|
||||
if (temp == 7) command=0x95;
|
||||
if (temp == 8) command=0xb8;
|
||||
if (temp == 9) command=0x84;
|
||||
if (temp ==10) command=0xa8;
|
||||
if (temp ==11) command=0x98;
|
||||
if (temp ==12) command=0xb2;
|
||||
if (temp ==13) command=0x8a;
|
||||
if (temp ==14) command=0xa2;
|
||||
if (temp ==15) command=0x92;
|
||||
} else // ON
|
||||
if (cmd==VALUE_ON) {
|
||||
if (temp == 0) command=0xb6;
|
||||
if (temp == 1) command=0x8e;
|
||||
if (temp == 2) command=0xa6;
|
||||
if (temp == 3) command=0x96;
|
||||
if (temp == 4) command=0xb9;
|
||||
if (temp == 5) command=0x85;
|
||||
if (temp == 6) command=0xa9;
|
||||
if (temp == 7) command=0x99;
|
||||
if (temp == 8) command=0xb0;
|
||||
if (temp == 9) command=0x88;
|
||||
if (temp ==10) command=0xa0;
|
||||
if (temp ==11) command=0x90;
|
||||
if (temp ==12) command=0xbc;
|
||||
if (temp ==13) command=0x82;
|
||||
if (temp ==14) command=0xac;
|
||||
if (temp ==15) command=0x9c;
|
||||
} else // AllON
|
||||
if (cmd==VALUE_ALLON) {
|
||||
command=0x93;
|
||||
} else // AllOff
|
||||
if (cmd==VALUE_ALLOFF) {
|
||||
command=0xa3;
|
||||
}
|
||||
command=command << 24;
|
||||
bitstream=bitstream+command;
|
||||
}
|
||||
RSL2_Send(bitstream); // the full bitstream to send
|
||||
success=true;
|
||||
}
|
||||
return success;
|
||||
}
|
||||
|
||||
void RSL2_Send(unsigned long address) {
|
||||
int fpulse = 650; // Pulse witdh in microseconds 650?
|
||||
int fpulse2 = 450; // Pulse witdh in microseconds 650?
|
||||
int fretrans = 4; // Number of code retransmissions
|
||||
uint32_t fdatabit;
|
||||
uint32_t fdatamask = 0x80000000;
|
||||
uint32_t fsendbuff;
|
||||
|
||||
digitalWrite(PIN_RF_RX_VCC,LOW); // Spanning naar de RF ontvanger uit om interferentie met de zender te voorkomen.
|
||||
digitalWrite(PIN_RF_TX_VCC,HIGH); // zet de 433Mhz zender aan
|
||||
delayMicroseconds(TRANSMITTER_STABLE_DELAY); // short delay to let the transmitter become stable (Note: Aurel RTX MID needs 500µS/0,5ms)
|
||||
|
||||
for (int nRepeat = 0; nRepeat <= fretrans; nRepeat++) {
|
||||
fsendbuff=address;
|
||||
|
||||
// send SYNC 1P High, 10P low
|
||||
digitalWrite(PIN_RF_TX_DATA, HIGH);
|
||||
delayMicroseconds(fpulse * 1);
|
||||
digitalWrite(PIN_RF_TX_DATA, LOW);
|
||||
delayMicroseconds(fpulse * 10);
|
||||
// end send SYNC
|
||||
// Send command
|
||||
for (int i = 0; i < 32; i++) { // 32 bits
|
||||
// read data bit
|
||||
fdatabit = fsendbuff & fdatamask; // Get most left bit
|
||||
fsendbuff = (fsendbuff << 1); // Shift left
|
||||
if (fdatabit != fdatamask) { // Write 0
|
||||
digitalWrite(PIN_RF_TX_DATA, HIGH);
|
||||
delayMicroseconds(fpulse2 * 1);
|
||||
digitalWrite(PIN_RF_TX_DATA, LOW);
|
||||
delayMicroseconds(fpulse2 * 3);
|
||||
} else { // Write 1
|
||||
digitalWrite(PIN_RF_TX_DATA, HIGH);
|
||||
delayMicroseconds(fpulse2 * 3);
|
||||
digitalWrite(PIN_RF_TX_DATA, LOW);
|
||||
delayMicroseconds(fpulse2 * 1);
|
||||
}
|
||||
}
|
||||
digitalWrite(PIN_RF_TX_DATA, HIGH);
|
||||
delayMicroseconds(fpulse2 * 1);
|
||||
digitalWrite(PIN_RF_TX_DATA, LOW);
|
||||
delayMicroseconds(fpulse * 14);
|
||||
}
|
||||
delayMicroseconds(TRANSMITTER_STABLE_DELAY); // short delay to let the transmitter become stable (Note: Aurel RTX MID needs 500µS/0,5ms)
|
||||
digitalWrite(PIN_RF_TX_VCC,LOW); // zet de 433Mhz zender weer uit
|
||||
digitalWrite(PIN_RF_RX_VCC,HIGH); // Spanning naar de RF ontvanger weer aan.
|
||||
RFLinkHW();
|
||||
}
|
||||
#endif // PLUGIN_TX_007
|
|
@ -0,0 +1,250 @@
|
|||
//#######################################################################################################
|
||||
//## This Plugin is only for use with the RFLink software package ##
|
||||
//## Plugin-008 Kambrook ##
|
||||
//#######################################################################################################
|
||||
/*********************************************************************************************\
|
||||
* This Plugin takes care of receiving of the Kambrook protocol
|
||||
* Device models: RF3399/RF3405/RF3672/RF3689/RF4471R
|
||||
* Made by Ningbo Comen Electronics Technology Co. Ltd.
|
||||
*
|
||||
* Author : StuntTeam
|
||||
* 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!
|
||||
*********************************************************************************************
|
||||
* Changelog: v1.0 initial release
|
||||
*********************************************************************************************
|
||||
* Technical information:
|
||||
* RF packets contain 96 pulses, 48 bits
|
||||
*
|
||||
* Kambrook Message Format:
|
||||
* AAAAAAAA BBBBBBBB BBBBBBBB BBBBBBBB CCCCCCCC DDDDDDDD
|
||||
*
|
||||
* A = Preamble, always 0x55
|
||||
* B = Address
|
||||
* C = Channel/Command
|
||||
* D = Trailing, always 0xFF
|
||||
*
|
||||
* Details http://wiki.beyondlogic.org/index.php?title=Reverse_engineering_the_RF_protocol_on_a_Kambrook_Power_Point_Controller
|
||||
*
|
||||
* 20;33;DEBUG;Pulses=96;Pulses(uSec)=270,180,600,180,210,180,600,180,210,180,600,180,210,180,600,180,210,180,210,180,210,180,210,180,210,180,210,180,210,180,210,180,210,180,210,180,210,180,210,180,210,180,210,180,210,180,210,180,210,180,210,180,210,180,210,180,210,180,210,180,210,180,600,180,210,180,210,180,210,180,210,180,210,180,210,180,210,180,600,180,600,180,600,180,600,180,600,180,600,180,600,180,600,180,600,6990;
|
||||
\*********************************************************************************************/
|
||||
#define KAMBROOK_PULSECOUNT 96
|
||||
#define KAMBROOK_PULSEMID 400/RAWSIGNAL_SAMPLE_RATE
|
||||
|
||||
#ifdef PLUGIN_008
|
||||
boolean Plugin_008(byte function, char *string) {
|
||||
if (RawSignal.Number != KAMBROOK_PULSECOUNT) return false;
|
||||
unsigned long address=0L;
|
||||
byte sync=0;
|
||||
byte command=0;
|
||||
byte trailing=0;
|
||||
|
||||
byte bitcounter=0;
|
||||
byte status=0;
|
||||
byte channel=0;
|
||||
byte subchan=0;
|
||||
//==================================================================================
|
||||
// get bits
|
||||
for(byte x=1;x<KAMBROOK_PULSECOUNT;x=x+2) {
|
||||
if (RawSignal.Pulses[x] > KAMBROOK_PULSEMID) {
|
||||
if (bitcounter < 8) {
|
||||
sync = (sync << 1) | 0x1;
|
||||
} else
|
||||
if (bitcounter < 32) {
|
||||
address = (address << 1) | 0x1;
|
||||
} else
|
||||
if (bitcounter < 40) {
|
||||
command = (command << 1) | 0x1;
|
||||
} else {
|
||||
trailing = (trailing << 1) | 0x1;
|
||||
}
|
||||
bitcounter++;
|
||||
} else {
|
||||
if (bitcounter < 8) {
|
||||
sync = (sync << 1);
|
||||
} else
|
||||
if (bitcounter < 32) {
|
||||
address = (address << 1);
|
||||
} else
|
||||
if (bitcounter < 40) {
|
||||
command = (command << 1);
|
||||
} else {
|
||||
trailing = (trailing << 1);
|
||||
}
|
||||
bitcounter++;
|
||||
}
|
||||
}
|
||||
//==================================================================================
|
||||
// all bits received, make sure checksum/sanity check is okay
|
||||
//==================================================================================
|
||||
if (sync != 0x55) return false;
|
||||
if (trailing != 0xff) return false;
|
||||
//==================================================================================
|
||||
// Prevent repeating signals from showing up
|
||||
//==================================================================================
|
||||
if(SignalHash!=SignalHashPrevious || RepeatingTimer<millis()) {
|
||||
// not seen the RF packet recently
|
||||
} else {
|
||||
// already seen the RF packet recently
|
||||
return true;
|
||||
}
|
||||
//==================================================================================
|
||||
//==================================================================================
|
||||
status=(command)&1; // 0/1 off/on
|
||||
|
||||
subchan=(((command) >> 1)&7) + 1; // button code
|
||||
if (status == 0) subchan--;
|
||||
|
||||
byte temp=(command) >> 4; // channel code
|
||||
channel=0x41+temp;
|
||||
//==================================================================================
|
||||
// Output
|
||||
// ----------------------------------
|
||||
sprintf(pbuffer, "20;%02X;", PKSequenceNumber++);// Node and packet number
|
||||
Serial.print( pbuffer );
|
||||
// ----------------------------------
|
||||
Serial.print(F("Kambrook;")); // Label
|
||||
sprintf(pbuffer, "ID=%06lx;",((address)&0xffffff) ); // ID
|
||||
Serial.print( pbuffer );
|
||||
sprintf(pbuffer, "SWITCH=%c%d;", channel,subchan);
|
||||
Serial.print( pbuffer );
|
||||
Serial.print(F("CMD=")); // command
|
||||
if (status==0) Serial.print(F("OFF;"));
|
||||
if (status==1) Serial.print(F("ON;"));
|
||||
Serial.println();
|
||||
//==================================================================================
|
||||
RawSignal.Repeats=true; // suppress repeats of the same RF packet
|
||||
RawSignal.Number=0;
|
||||
return true;
|
||||
}
|
||||
#endif // PLUGIN_008
|
||||
|
||||
#ifdef PLUGIN_TX_008
|
||||
void Kambrook_Send(unsigned long address);
|
||||
|
||||
boolean PluginTX_008(byte function, char *string) {
|
||||
boolean success=false;
|
||||
//10;kambrook;050325;a1;ON;
|
||||
//012345678901234567890123
|
||||
if (strncasecmp(InputBuffer_Serial+3,"KAMBROOK;",9) == 0) { // KAKU Command eg.
|
||||
if (InputBuffer_Serial[18] != ';') return false;
|
||||
|
||||
InputBuffer_Serial[10]=0x30;
|
||||
InputBuffer_Serial[11]=0x78; // Get address from hexadecimal value
|
||||
InputBuffer_Serial[18]=0x00; // Get address from hexadecimal value
|
||||
|
||||
unsigned long bitstream=0L; // Main placeholder
|
||||
byte Home=0; // channel A..D
|
||||
byte Address=0; // subchannel 1..5
|
||||
byte c;
|
||||
byte x=19; // teller die wijst naar het te behandelen teken
|
||||
|
||||
bitstream=str2int(InputBuffer_Serial+10); // Address
|
||||
|
||||
while((c=tolower(InputBuffer_Serial[x++]))!=';') {
|
||||
if(c>='0' && c<='9'){Address=Address+c-'0';} // Home 0..9
|
||||
if(c>='a' && c<='d'){Home=c-'a';} // Address a..d
|
||||
}
|
||||
|
||||
Address=Address << 1; // shift left 1 bit
|
||||
c=0;
|
||||
c = str2cmd(InputBuffer_Serial+x); // ON/OFF command
|
||||
if (c == VALUE_ON) {
|
||||
Address--;
|
||||
}
|
||||
Address=Address & 0x0f;
|
||||
// -------------------------------
|
||||
Home = Home << 4; // move home to bits 4-7
|
||||
bitstream=(bitstream) << 8; // shift main value 8 bits left
|
||||
bitstream=bitstream + Home; // add to main value
|
||||
bitstream=bitstream + Address; // add address bits to bits 0-3
|
||||
// -------------------------------
|
||||
Kambrook_Send(bitstream); // bitstream to send
|
||||
success=true;
|
||||
}
|
||||
return success;
|
||||
}
|
||||
|
||||
void Kambrook_Send(unsigned long address) {
|
||||
int fpulse = 300; // Pulse witdh in microseconds
|
||||
int fpulse2 = 700; // Pulse witdh in microseconds
|
||||
int fretrans = 5; // Number of code retransmissions
|
||||
uint32_t fdatabit;
|
||||
uint32_t fdatamask = 0x800000;
|
||||
uint32_t fsendbuff;
|
||||
|
||||
digitalWrite(PIN_RF_RX_VCC,LOW); // Spanning naar de RF ontvanger uit om interferentie met de zender te voorkomen.
|
||||
digitalWrite(PIN_RF_TX_VCC,HIGH); // zet de 433Mhz zender aan
|
||||
delayMicroseconds(TRANSMITTER_STABLE_DELAY); // short delay to let the transmitter become stable (Note: Aurel RTX MID needs 500µS/0,5ms)
|
||||
for (int nRepeat = 0; nRepeat <= fretrans; nRepeat++) {
|
||||
// --------------
|
||||
// Send preamble (0x55) - 8 bits
|
||||
fsendbuff=0x55;
|
||||
fdatamask=0x80;
|
||||
for (int i = 0; i < 8; i++) { // Preamble
|
||||
// read data bit
|
||||
fdatabit = fsendbuff & fdatamask; // Get most left bit
|
||||
fsendbuff = (fsendbuff << 1); // Shift left
|
||||
if (fdatabit != fdatamask) { // Write 0
|
||||
digitalWrite(PIN_RF_TX_DATA, HIGH);
|
||||
delayMicroseconds(fpulse);
|
||||
digitalWrite(PIN_RF_TX_DATA, LOW);
|
||||
delayMicroseconds(fpulse);
|
||||
} else { // Write 1
|
||||
digitalWrite(PIN_RF_TX_DATA, HIGH);
|
||||
delayMicroseconds(fpulse2);
|
||||
digitalWrite(PIN_RF_TX_DATA, LOW);
|
||||
delayMicroseconds(fpulse);
|
||||
}
|
||||
}
|
||||
// --------------
|
||||
fsendbuff=address;
|
||||
fdatamask=0x80000000;
|
||||
// Send command (channel/address/status) - 32 bits
|
||||
for (int i = 0; i < 32;i++){ //28;i++){
|
||||
// read data bit
|
||||
fdatabit = fsendbuff & fdatamask; // Get most left bit
|
||||
fsendbuff = (fsendbuff << 1); // Shift left
|
||||
if (fdatabit != fdatamask) { // Write 0
|
||||
digitalWrite(PIN_RF_TX_DATA, HIGH);
|
||||
delayMicroseconds(fpulse);
|
||||
digitalWrite(PIN_RF_TX_DATA, LOW);
|
||||
delayMicroseconds(fpulse);
|
||||
} else { // Write 1
|
||||
digitalWrite(PIN_RF_TX_DATA, HIGH);
|
||||
delayMicroseconds(fpulse2);
|
||||
digitalWrite(PIN_RF_TX_DATA, LOW);
|
||||
delayMicroseconds(fpulse);
|
||||
}
|
||||
}
|
||||
// --------------
|
||||
// Send trailing bits - 8 bits
|
||||
fsendbuff=0xFF;
|
||||
fdatamask=0x80;
|
||||
for (int i = 0; i < 8; i++) {
|
||||
// read data bit
|
||||
fdatabit = fsendbuff & fdatamask; // Get most left bit
|
||||
fsendbuff = (fsendbuff << 1); // Shift left
|
||||
if (fdatabit != fdatamask) { // Write 0
|
||||
digitalWrite(PIN_RF_TX_DATA, HIGH);
|
||||
delayMicroseconds(fpulse);
|
||||
digitalWrite(PIN_RF_TX_DATA, LOW);
|
||||
delayMicroseconds(fpulse);
|
||||
} else { // Write 1
|
||||
digitalWrite(PIN_RF_TX_DATA, HIGH);
|
||||
delayMicroseconds(fpulse2);
|
||||
digitalWrite(PIN_RF_TX_DATA, LOW);
|
||||
delayMicroseconds(fpulse);
|
||||
}
|
||||
}
|
||||
// --------------
|
||||
digitalWrite(PIN_RF_TX_DATA, LOW);
|
||||
delayMicroseconds(fpulse2 * 14);
|
||||
}
|
||||
delayMicroseconds(TRANSMITTER_STABLE_DELAY); // short delay to let the transmitter become stable (Note: Aurel RTX MID needs 500µS/0,5ms)
|
||||
digitalWrite(PIN_RF_TX_VCC,LOW); // zet de 433Mhz zender weer uit
|
||||
digitalWrite(PIN_RF_RX_VCC,HIGH); // Spanning naar de RF ontvanger weer aan.
|
||||
RFLinkHW();
|
||||
}
|
||||
#endif // PLUGIN_008
|
|
@ -0,0 +1,347 @@
|
|||
//#######################################################################################################
|
||||
//## This Plugin is only for use with the RFLink software package ##
|
||||
//## Plugin-06: X10 RF ##
|
||||
//#######################################################################################################
|
||||
/*********************************************************************************************\
|
||||
* This plugin takes care of sending and receiving the X10 RF protocol.
|
||||
*
|
||||
* Author : StuntTeam
|
||||
* 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!
|
||||
***********************************************************************************************
|
||||
* Incoming event: "X10 <adres>, <On | Off>
|
||||
* Send : "X10Send <Adres>, <On | Off>
|
||||
*
|
||||
* Address = A1 - P16
|
||||
***********************************************************************************************
|
||||
* Technical information:
|
||||
* RF packets are 68 bits long transferring 64 manchester encoded bits resulting in 32 bits / 4 bytes.
|
||||
*
|
||||
* address address^ data data^
|
||||
* 01100000 10011111 00000000 11111111 609F00FF
|
||||
* 10011111 01100000 11111111 00000000 9F60FF00
|
||||
*
|
||||
* 4 bytes are transmitted, the second and fourth are the inverse of the first and third byte.
|
||||
* So the actual data is only 2 bytes
|
||||
*
|
||||
* 01100000 00000000
|
||||
* AAAABBBB CDEDDDDD
|
||||
*
|
||||
* A = Housecode 0110 a 6 0111 b 7 0100 c 4 0101 d 5 1000 e 8 1001 f 9 1010 g a 1011 h b
|
||||
* 1110 i e 1111 j f 1100 k c 1101 l d 0000 m 0 0001 n 1 0010 o 2 0011 p 3
|
||||
* B = Unitcode 1-8 / 9-16 indicator
|
||||
* C = Group/Dimmer indicator
|
||||
* D = Unitcode
|
||||
* E = on/off indicator
|
||||
*
|
||||
* on
|
||||
* 20;06;DEBUG;Pulses=68;Pulses(uSec)=3300,4225,400,375,400,1325,400,1325,400,1325,400,375,400,375,400,375,400,375,400,1325,400,375,400,375,400,375,400,1350,400,1350,375,1350,400,1350,400,375,400,375,400,375,400,1325,400,1325,400,375,400,375,400,375,400,1350,400,1325,400,1325,400,375,400,375,400,1325,400,1325,400,1325,400
|
||||
* off
|
||||
* 20;10;DEBUG;Pulses=68;Pulses(uSec)=3300,4225,400,375,400,1350,400,1350,400,1325,400,375,400,375,400,375,400,375,400,1325,400,375,400,375,400,375,400,1325,400,1325,400,1325,400,1325,400,375,400,375,400,1325,400,1350,400,1350,400,375,400,375,400,375,375,1350,400,1350,400,375,400,375,400,375,400,1325,400,1350,400,1325,400;
|
||||
* 20;20;DEBUG;Pulses=66;Pulses(uSec)=425,350,375,1300,375,1300,375,1350,375,375,375,1350,375,375,375,375,375,1350,375,375,375,375,375,375,400,1350,375,375,400,1350,375,1350,400,1325,400,375,400,375,400,375,400,375,400,375,400,375,400,375,400,375,400,1325,400,1325,400,1325,400,1325,400,1325,400,1350,375,1350,375;
|
||||
\*********************************************************************************************/
|
||||
#define X10_PulseLength 66
|
||||
#define X10_PULSEMID 600/RAWSIGNAL_SAMPLE_RATE
|
||||
|
||||
#ifdef PLUGIN_009
|
||||
boolean Plugin_009(byte function, char *string) {
|
||||
if ( (RawSignal.Number != (X10_PulseLength )) && (RawSignal.Number != (X10_PulseLength+2)) ) return false;
|
||||
unsigned long bitstream=0L;
|
||||
byte housecode=0;
|
||||
byte unitcode=0;
|
||||
byte command=0;
|
||||
byte data[4];
|
||||
byte start=0;
|
||||
if (RawSignal.Number == X10_PulseLength+2) {
|
||||
if ( (RawSignal.Pulses[1]*RawSignal.Multiply > 3000) && (RawSignal.Pulses[2]*RawSignal.Multiply > 3000) ) {
|
||||
start=2;
|
||||
} else {
|
||||
return false; // not an X10 packet
|
||||
}
|
||||
}
|
||||
// get all 24 bits
|
||||
for(byte x=2+start;x < ((X10_PulseLength)+start) ;x+=2) {
|
||||
if(RawSignal.Pulses[x] > X10_PULSEMID) {
|
||||
bitstream = (bitstream << 1) | 0x1;
|
||||
} else {
|
||||
bitstream = (bitstream << 1);
|
||||
}
|
||||
}
|
||||
//==================================================================================
|
||||
// Prevent repeating signals from showing up
|
||||
//==================================================================================
|
||||
if(SignalHash!=SignalHashPrevious || RepeatingTimer<millis()) {
|
||||
// not seen the RF packet recently
|
||||
if (bitstream == 0) return false; // sanity check
|
||||
} else {
|
||||
// already seen the RF packet recently
|
||||
return true;
|
||||
}
|
||||
//==================================================================================
|
||||
// order received data
|
||||
data[0]=((bitstream)>>24)&0xff;
|
||||
data[1]=((bitstream)>>16)&0xff;
|
||||
data[2]=((bitstream)>>8)&0xff;
|
||||
data[3]=(bitstream)&0xff;
|
||||
// ----------------------------------
|
||||
// perform sanity checks
|
||||
data[1]=data[1]^0xff;
|
||||
data[3]=data[3]^0xff;
|
||||
if (data[0] != data[1]) return false;
|
||||
if (data[2] != data[3]) return false;
|
||||
// ----------------------------------
|
||||
data[1]=data[1]&0x0f; // lower nibble only
|
||||
data[0]=data[0]&0xf0; // upper nibble only
|
||||
|
||||
housecode=0;
|
||||
if (data[0]==0x60) housecode=0;
|
||||
if (data[0]==0x70) housecode=1;
|
||||
if (data[0]==0x40) housecode=2;
|
||||
if (data[0]==0x50) housecode=3;
|
||||
if (data[0]==0x80) housecode=4;
|
||||
if (data[0]==0x90) housecode=5;
|
||||
if (data[0]==0xa0) housecode=6;
|
||||
if (data[0]==0xb0) housecode=7;
|
||||
if (data[0]==0xe0) housecode=8;
|
||||
if (data[0]==0xf0) housecode=9;
|
||||
if (data[0]==0xc0) housecode=10;
|
||||
if (data[0]==0xd0) housecode=11;
|
||||
if (data[0]==0x00) housecode=12;
|
||||
if (data[0]==0x10) housecode=13;
|
||||
if (data[0]==0x20) housecode=14;
|
||||
if (data[0]==0x30) housecode=15;
|
||||
|
||||
if (data[2]==0x00) { unitcode=1; command=1;}
|
||||
if (data[2]==0x20) { unitcode=1; command=0;}
|
||||
if (data[2]==0x10) { unitcode=2; command=1;}
|
||||
if (data[2]==0x30) { unitcode=2; command=0;}
|
||||
if (data[2]==0x08) { unitcode=3; command=1;}
|
||||
if (data[2]==0x28) { unitcode=3; command=0;}
|
||||
if (data[2]==0x18) { unitcode=4; command=1;}
|
||||
if (data[2]==0x38) { unitcode=4; command=0;}
|
||||
if (data[2]==0x40) { unitcode=5; command=1;}
|
||||
if (data[2]==0x60) { unitcode=5; command=0;}
|
||||
if (data[2]==0x50) { unitcode=6; command=1;}
|
||||
if (data[2]==0x70) { unitcode=6; command=0;}
|
||||
if (data[2]==0x48) { unitcode=7; command=1;}
|
||||
if (data[2]==0x68) { unitcode=7; command=0;}
|
||||
if (data[2]==0x58) { unitcode=8; command=1;}
|
||||
if (data[2]==0x78) { unitcode=8; command=0;}
|
||||
if (data[2]==0x88) { unitcode=0; command=2;}
|
||||
if (data[2]==0x98) { unitcode=0; command=3;}
|
||||
if (data[2]==0x80) { unitcode=0; command=4;}
|
||||
if (data[2]==0x90) { unitcode=0; command=5;}
|
||||
|
||||
if ( (data[1]==0x04) && (command < 2) ) {
|
||||
unitcode=unitcode+8;
|
||||
}
|
||||
//==================================================================================
|
||||
// ----------------------------------
|
||||
// All is OK, build event
|
||||
// ----------------------------------
|
||||
// Output
|
||||
// ----------------------------------
|
||||
sprintf(pbuffer, "20;%02X;", PKSequenceNumber++); // Node and packet number
|
||||
Serial.print( pbuffer );
|
||||
// ----------------------------------
|
||||
Serial.print(F("X10;")); // Label
|
||||
sprintf(pbuffer, "ID=%02x;", 0x41+housecode); // ID
|
||||
Serial.print( pbuffer );
|
||||
sprintf(pbuffer, "SWITCH=%d;", unitcode);
|
||||
Serial.print( pbuffer );
|
||||
Serial.print(F("CMD="));
|
||||
if ( command == 0) {
|
||||
Serial.print(F("OFF;"));
|
||||
} else
|
||||
if ( command == 1) {
|
||||
Serial.print(F("ON;"));
|
||||
} else
|
||||
if ( command == 2) {
|
||||
Serial.print(F("BRIGHT;"));
|
||||
} else
|
||||
if ( command == 3) {
|
||||
Serial.print(F("DIM;"));
|
||||
} else
|
||||
if ( command == 4) {
|
||||
Serial.print(F("ALLOFF;"));
|
||||
} else
|
||||
if ( command == 5) {
|
||||
Serial.print(F("ALLON;"));
|
||||
}
|
||||
Serial.println();
|
||||
// ----------------------------------
|
||||
RawSignal.Repeats=true; // suppress repeats of the same RF packet
|
||||
RawSignal.Number=0;
|
||||
return true;
|
||||
}
|
||||
#endif //PLUGIN_009
|
||||
|
||||
#ifdef PLUGIN_TX_009
|
||||
void X10_Send(uint32_t address);
|
||||
|
||||
boolean PluginTX_009(byte function, char *string) {
|
||||
boolean success=false;
|
||||
//10;X10;000041;1;OFF;
|
||||
//0123456789012345678
|
||||
// Hier aangekomen bevat string het volledige commando. Test als eerste of het opgegeven commando overeen komt
|
||||
if (strncasecmp(InputBuffer_Serial+3,"X10;",4) == 0) { // X10 Command eg.
|
||||
unsigned long bitstream=0L;
|
||||
byte x=14; // teller die wijst naar het te behandelen teken
|
||||
byte command=0;
|
||||
byte Home=0; // Home A..P
|
||||
byte Address=0; // Blyss subchannel 1..5
|
||||
byte c;
|
||||
uint32_t newadd=0;
|
||||
|
||||
InputBuffer_Serial[ 9]=0x30;
|
||||
InputBuffer_Serial[10]=0x78;
|
||||
InputBuffer_Serial[13]=0;
|
||||
Home=str2int(InputBuffer_Serial+9); // Home: A..P
|
||||
if (Home < 0x51) // take care of upper/lower case
|
||||
Home=Home - 'A';
|
||||
else
|
||||
if (Home < 0x71) // take care of upper/lower case
|
||||
Home=Home - 'a';
|
||||
else {
|
||||
return success; // invalid value
|
||||
}
|
||||
|
||||
while((c=tolower(InputBuffer_Serial[x++]))!=';'){ // Address: 1 to 16
|
||||
if(c>='0' && c<='9'){Address=Address*10;Address=Address+c-'0';}
|
||||
}
|
||||
|
||||
if (Home == 0) c = 0x60;
|
||||
if (Home == 1) c = 0x70;
|
||||
if (Home == 2) c = 0x40;
|
||||
if (Home == 3) c = 0x50;
|
||||
if (Home == 4) c = 0x80;
|
||||
if (Home == 5) c = 0x90;
|
||||
if (Home == 6) c = 0xa0;
|
||||
if (Home == 7) c = 0xb0;
|
||||
if (Home == 8) c = 0xe0;
|
||||
if (Home == 9) c = 0xf0;
|
||||
if (Home ==10) c = 0xc0;
|
||||
if (Home ==11) c = 0xd0;
|
||||
if (Home ==12) c = 0x00;
|
||||
if (Home ==13) c = 0x10;
|
||||
if (Home ==14) c = 0x20;
|
||||
if (Home ==15) c = 0x30;
|
||||
if (Address > 7) {
|
||||
c = c + 4;
|
||||
Address=Address-8;
|
||||
}
|
||||
// ---------------
|
||||
Home=str2cmd(InputBuffer_Serial+x);
|
||||
if (Home == 0) { // DIM/BRIGHT command
|
||||
if (strcasecmp(InputBuffer_Serial+x,"DIM")==0) {
|
||||
command=3;
|
||||
} else
|
||||
if (strcasecmp(InputBuffer_Serial+x,"BRIGHT")==0) {
|
||||
command=2;
|
||||
}
|
||||
c = c + 4;
|
||||
} else {
|
||||
if (Home==VALUE_ON) {
|
||||
command=1;
|
||||
} else
|
||||
if (Home==VALUE_OFF) {
|
||||
command=0;
|
||||
} else
|
||||
if (Home==VALUE_ALLOFF) {
|
||||
command=4;
|
||||
c = c + 4;
|
||||
} else
|
||||
if (Home==VALUE_ALLON) {
|
||||
command=5;
|
||||
c = c + 4;
|
||||
}
|
||||
}
|
||||
if (Address == 1 && command == 1) bitstream=0x00;
|
||||
if (Address == 1 && command == 0) bitstream=0x20;
|
||||
if (Address == 2 && command == 1) bitstream=0x10;
|
||||
if (Address == 2 && command == 0) bitstream=0x30;
|
||||
if (Address == 3 && command == 1) bitstream=0x08;
|
||||
if (Address == 3 && command == 0) bitstream=0x28;
|
||||
if (Address == 4 && command == 1) bitstream=0x18;
|
||||
if (Address == 4 && command == 0) bitstream=0x38;
|
||||
if (Address == 5 && command == 1) bitstream=0x40;
|
||||
if (Address == 5 && command == 0) bitstream=0x60;
|
||||
if (Address == 6 && command == 1) bitstream=0x50;
|
||||
if (Address == 6 && command == 0) bitstream=0x70;
|
||||
if (Address == 7 && command == 1) bitstream=0x48;
|
||||
if (Address == 7 && command == 0) bitstream=0x68;
|
||||
if (Address == 8 && command == 1) bitstream=0x58;
|
||||
if (Address == 8 && command == 0) bitstream=0x78;
|
||||
if (command == 2) bitstream=0x88;
|
||||
if (command == 3) bitstream=0x98;
|
||||
if (command == 4) bitstream=0x80;
|
||||
if (command == 5) bitstream=0x90;
|
||||
// -----------------------------
|
||||
newadd=bitstream <<8;
|
||||
bitstream=bitstream^0xff;
|
||||
newadd=newadd+bitstream;
|
||||
bitstream=c^0xff;
|
||||
bitstream=bitstream<<16;
|
||||
newadd=newadd+bitstream;
|
||||
bitstream=c;
|
||||
bitstream=bitstream<<24;
|
||||
newadd=newadd+bitstream;
|
||||
bitstream=newadd;
|
||||
// -----------------------------
|
||||
X10_Send(bitstream); // full bitstream to send
|
||||
success=true;
|
||||
}
|
||||
return success;
|
||||
}
|
||||
|
||||
void X10_Send(uint32_t address) {
|
||||
int fpulse = 375; // Pulse witdh in microseconds
|
||||
int fretrans = 4; // Number of code retransmissions
|
||||
uint32_t fdatabit;
|
||||
uint32_t fdatamask = 0x80000000;
|
||||
uint32_t fsendbuff;
|
||||
|
||||
digitalWrite(PIN_RF_RX_VCC,LOW); // Disable RF receiver
|
||||
digitalWrite(PIN_RF_TX_VCC,HIGH); // Enable RF transmitter
|
||||
delayMicroseconds(TRANSMITTER_STABLE_DELAY); // short delay to let the transmitter become stable (Note: Aurel RTX MID needs 500µS/0,5ms)
|
||||
|
||||
for (int nRepeat = 0; nRepeat <= fretrans; nRepeat++) {
|
||||
fsendbuff=address;
|
||||
|
||||
// send SYNC 12P High, 10P low
|
||||
digitalWrite(PIN_RF_TX_DATA, HIGH);
|
||||
delayMicroseconds(fpulse * 12);
|
||||
digitalWrite(PIN_RF_TX_DATA, LOW);
|
||||
delayMicroseconds(fpulse * 10);
|
||||
// end send SYNC
|
||||
// Send command
|
||||
for (int i = 0; i < 32; i++) { // 32 bits
|
||||
// read data bit
|
||||
fdatabit = fsendbuff & fdatamask; // Get most left bit
|
||||
fsendbuff = (fsendbuff << 1); // Shift left
|
||||
if (fdatabit != fdatamask) { // Write 0
|
||||
digitalWrite(PIN_RF_TX_DATA, HIGH);
|
||||
delayMicroseconds(fpulse * 1);
|
||||
digitalWrite(PIN_RF_TX_DATA, LOW);
|
||||
delayMicroseconds(fpulse * 1);
|
||||
} else { // Write 1
|
||||
digitalWrite(PIN_RF_TX_DATA, HIGH);
|
||||
delayMicroseconds(fpulse * 1);
|
||||
digitalWrite(PIN_RF_TX_DATA, LOW);
|
||||
delayMicroseconds(fpulse * 4);
|
||||
}
|
||||
}
|
||||
// Send Stop/delay
|
||||
digitalWrite(PIN_RF_TX_DATA, HIGH);
|
||||
delayMicroseconds(fpulse * 1);
|
||||
digitalWrite(PIN_RF_TX_DATA, LOW);
|
||||
delayMicroseconds(fpulse * 20);
|
||||
}
|
||||
delayMicroseconds(TRANSMITTER_STABLE_DELAY); // short delay to let the transmitter become stable (Note: Aurel RTX MID needs 500µS/0,5ms)
|
||||
digitalWrite(PIN_RF_TX_VCC,LOW); // Disable RF transmitter
|
||||
digitalWrite(PIN_RF_RX_VCC,HIGH); // Enable RF receiver
|
||||
RFLinkHW();
|
||||
return;
|
||||
}
|
||||
#endif //PLUGIN_TX_009
|
|
@ -0,0 +1,242 @@
|
|||
|
||||
//## This Plugin is only for use with the RFLink software package ##
|
||||
//## Plugin-10 TRC02 RGB Controller ##
|
||||
//#######################################################################################################
|
||||
/*********************************************************************************************\
|
||||
* Decodes signals from a wireless RGB TRC02 controller remote control
|
||||
*
|
||||
*
|
||||
* Author : StuntTeam, Marek Zlatos,
|
||||
* 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!
|
||||
*********************************************************************************************
|
||||
* Changelog: v1.0 initial release
|
||||
*********************************************************************************************
|
||||
* Technical information:
|
||||
* Decodes signals from a wireless TRC02 RGB controller remote control
|
||||
* --------------------------------------------------------------------------------------------
|
||||
* _Byte 0_ _Byte 1_ _Byte 2_ _Byte 3_ _Bit_
|
||||
* 76543210 76543210 76543210 76543210 0
|
||||
* AAAAAAAA BBBBBBBB CCCCCCCC DDDDDDDD E
|
||||
*
|
||||
* A = Rolling Code
|
||||
* B = Rolling Code
|
||||
* C = Rolling Code
|
||||
* D = Command
|
||||
* E = Checksum. bit is XOR of all bits in the RF message
|
||||
*
|
||||
* Commands:
|
||||
* 00 ON
|
||||
* 01 OFF
|
||||
* 02 Dim Down
|
||||
* 03 DIM UP
|
||||
* 05 Color Mix UP
|
||||
* 04 Color Mix Down
|
||||
* 87 Color Wheel Red
|
||||
* 34 Color Wheel Blue
|
||||
* 78 Color Wheel Yellow
|
||||
* 5D Color Wheel Green
|
||||
*
|
||||
* Sample:
|
||||
* 20;30;DEBUG;Pulses=180;Pulses(uSec)=450,420,420,420,420,420,1410,960,420,420,420,420,420,420,420,420,420,420,930,420,420,960,420,420,420,420,420,420,420,420,420,420,930,960,420,420,420,420,930,420,420,420,420,420,420,960,420,420,420,420,420,420,420,420,420,420,420,420,420,420,420,420,420,420,930,390,1440,960,420,420,420,420,420,420,420,420,420,420,930,420,420,960,420,420,420,420,420,420,420,420,420,420,930,960,420,420,420,420,930,420,420,420,420,420,420,960,420,420,420,420,420,420,420,420,420,420,420,420,420,420,420,420,420,420,930,390,1440,960,420,420,420,420,420,420,420,420,420,420,930,420,420,960,420,420,420,420,420,420,420,420,420,420,930,960,420,420,420,420,930,420,420,420,420,420,420,960,420,420,420,420,420,420,420,420,420,420,420,420,420,420,420,420,420,420,930,6990
|
||||
* TRC02:00000011 00000010 00111100 00000000 1
|
||||
* 20;01;TRC02;ID=03023c;SWITCH=00;CMD=ON;
|
||||
\*********************************************************************************************/
|
||||
#define RGB_MIN_PULSECOUNT 180
|
||||
#define RGB_MAX_PULSECOUNT 186
|
||||
|
||||
#define RGB_PULSE_STHI 1600/RAWSIGNAL_SAMPLE_RATE
|
||||
#define RGB_PULSE_STLO 1300/RAWSIGNAL_SAMPLE_RATE
|
||||
#define RGB_PULSE_HIHI 1100/RAWSIGNAL_SAMPLE_RATE
|
||||
#define RGB_PULSE_HILO 900/RAWSIGNAL_SAMPLE_RATE
|
||||
#define RGB_PULSE_LOHI 600/RAWSIGNAL_SAMPLE_RATE
|
||||
#define RGB_PULSE_LOLO 400/RAWSIGNAL_SAMPLE_RATE
|
||||
|
||||
#ifdef PLUGIN_010
|
||||
boolean Plugin_010(byte function, char *string) {
|
||||
if (RawSignal.Number < RGB_MIN_PULSECOUNT || RawSignal.Number > RGB_MAX_PULSECOUNT) return false;
|
||||
unsigned long bitstream=0L; // holds first 32 bits
|
||||
|
||||
byte checksum=0; // holds the checksum calculation
|
||||
byte crc=0; // holds the crc bit from the signal
|
||||
byte bitcounter=0; // counts number of received bits (converted from pulses)
|
||||
byte halfbit=0; // high pulse = 1, 2 low pulses = 0, halfbit keeps track of low pulses
|
||||
byte bitmask = 0;
|
||||
int command=0;
|
||||
byte start_stop=0;
|
||||
byte x=1;
|
||||
//==================================================================================
|
||||
for(x=1;x <RawSignal.Number-2;x++) { // get bytes
|
||||
if (start_stop!=0x01) {
|
||||
//if (RawSignal.Pulses[x]*RawSignal.Multiply > 1200 && RawSignal.Pulses[x]*RawSignal.Multiply < 1500) {
|
||||
if (RawSignal.Pulses[x] > RGB_PULSE_STLO && RawSignal.Pulses[x] < RGB_PULSE_STHI) {
|
||||
start_stop=0x01;
|
||||
continue;
|
||||
} else {
|
||||
if (x > 100) return false; // bad packet
|
||||
continue;
|
||||
}
|
||||
}
|
||||
if (RawSignal.Pulses[x]*RawSignal.Multiply > 750 && RawSignal.Pulses[x]*RawSignal.Multiply < 1000) {
|
||||
if (halfbit==1) { // cant receive a 1 bit after a single low value
|
||||
return false; // pulse error, must not be a UPM packet or reception error
|
||||
}
|
||||
bitmask = !bitmask;
|
||||
if (bitcounter < 32) {
|
||||
if (bitmask == 1){
|
||||
bitstream = (bitstream << 1);
|
||||
} else {
|
||||
bitstream = (bitstream << 1) | 0x1;
|
||||
}
|
||||
bitcounter++; // only need to count the first 10 bits
|
||||
} else {
|
||||
crc =1;
|
||||
break;
|
||||
}
|
||||
halfbit=0; // wait for next first low or high pulse
|
||||
} else {
|
||||
if (RawSignal.Pulses[x]*RawSignal.Multiply > 625 && RawSignal.Pulses[x]*RawSignal.Multiply < 250) return false; // Not a valid UPM pulse length
|
||||
if (halfbit == 0) { // 2 times a low value = 0 bit
|
||||
halfbit=1; // first half received
|
||||
} else {
|
||||
if (bitcounter < 32) {
|
||||
if (bitmask == 1){
|
||||
bitstream = (bitstream << 1);
|
||||
} else {
|
||||
bitstream = (bitstream << 1) | 0x1;
|
||||
}
|
||||
checksum=checksum^1;
|
||||
bitcounter++; // only need to count the first 10 bits
|
||||
} else {
|
||||
crc=0;
|
||||
break;
|
||||
}
|
||||
halfbit=0; // wait for next first low or high pulse
|
||||
}
|
||||
}
|
||||
}
|
||||
//==================================================================================
|
||||
// Validity checks
|
||||
if (RawSignal.Pulses[x+2]*RawSignal.Multiply < 1200 || RawSignal.Pulses[x+2]*RawSignal.Multiply > 1500) return false;
|
||||
//==================================================================================
|
||||
// perform a checksum check to make sure the packet is a valid RGB control packet
|
||||
// Checksum: xor all odd and all even bits should match the last bit
|
||||
// ----------------------------------
|
||||
if (checksum != crc) {
|
||||
//Serial.println("crc2 error");
|
||||
return false;
|
||||
}
|
||||
//==================================================================================
|
||||
// now process the command
|
||||
//==================================================================================
|
||||
command = (bitstream) &0xff; // command
|
||||
int id3 = (bitstream >> 8) &0xff;
|
||||
bitstream = (bitstream >> 16) &0xffff; // rolling code
|
||||
//==================================================================================
|
||||
// Output
|
||||
// ----------------------------------
|
||||
sprintf(pbuffer, "20;%02X;", PKSequenceNumber++); // Node and packet number
|
||||
Serial.print( pbuffer );
|
||||
Serial.print(F("TRC02RGB;")); // Label
|
||||
sprintf(pbuffer, "ID=%04x", bitstream); // ID
|
||||
Serial.print( pbuffer );
|
||||
sprintf(pbuffer, "%02x;", id3);
|
||||
Serial.print( pbuffer );
|
||||
sprintf(pbuffer, "SWITCH=%02x;", command);
|
||||
Serial.print( pbuffer );
|
||||
Serial.print(F("CMD="));
|
||||
if (command==0x00) Serial.print("ON;");
|
||||
else if (command==0x01) Serial.print(F("OFF;"));
|
||||
else if (command==0x02) Serial.print(F("DIM DOWN;"));
|
||||
else if (command==0x03) Serial.print(F("DIM UP;"));
|
||||
else if (command==0x05) Serial.print(F("COLORMIX UP;"));
|
||||
else if (command==0x04) Serial.print(F("COLORMIX DOWN;"));
|
||||
else if (command==0x87) Serial.print(F("COLOR RED;"));
|
||||
else if (command==0x34) Serial.print(F("COLOR BLUE;"));
|
||||
else if (command==0x78) Serial.print(F("COLOR YELLOW;"));
|
||||
else if (command==0x5D) Serial.print(F("COLOR GREEN;"));
|
||||
else {
|
||||
sprintf(pbuffer, "SET_LEVEL=%d;", command );
|
||||
Serial.print( pbuffer );
|
||||
}
|
||||
Serial.println();
|
||||
//==================================================================================
|
||||
RawSignal.Repeats=true; // suppress repeats of the same RF packet
|
||||
RawSignal.Number=0;
|
||||
return true;
|
||||
}
|
||||
#endif // PLUGIN_010
|
||||
|
||||
#ifdef PLUGIN_TX_010
|
||||
void TRC02_Send(unsigned long address, int command);
|
||||
|
||||
boolean PluginTX_010(byte function, char *string) {
|
||||
//10;TRC02RGB;03023c;00;
|
||||
//012345678901234567890123456
|
||||
boolean success=false;
|
||||
if (strncasecmp(InputBuffer_Serial+3,"TRC02RGB;",9) == 0) { // KAKU Command eg.
|
||||
TRC02_Send(strtoul(InputBuffer_Serial+12,NULL,16),strtoul(InputBuffer_Serial+19,NULL,16));
|
||||
success=true;
|
||||
}
|
||||
return success;
|
||||
}
|
||||
|
||||
void TRC02_Send(unsigned long address, int command) {
|
||||
int fpulse = 500;
|
||||
int fretrans = 2; // Number of code retransmissions
|
||||
byte crc = 0;
|
||||
uint32_t fdatabit;
|
||||
uint32_t fdatamask = 0x80000000;
|
||||
uint32_t fsendbuff;
|
||||
|
||||
digitalWrite(PIN_RF_RX_VCC,LOW); // Turn off power to the RF receiver
|
||||
digitalWrite(PIN_RF_TX_VCC,HIGH); // Enable the 433Mhz transmitter
|
||||
delayMicroseconds(TRANSMITTER_STABLE_DELAY); // short delay to let the transmitter become stable (Note: Aurel RTX MID needs 500µS/0,5ms)
|
||||
|
||||
for (int nRepeat = 0; nRepeat <= fretrans; nRepeat++) {
|
||||
crc=0;
|
||||
fsendbuff=address;
|
||||
fsendbuff=(fsendbuff<<8)+command;
|
||||
digitalWrite(PIN_RF_TX_DATA, HIGH); // start pulse
|
||||
delayMicroseconds(fpulse * 3);
|
||||
digitalWrite(PIN_RF_TX_DATA, LOW);
|
||||
delayMicroseconds(fpulse);
|
||||
for (int i = 0; i < 32; i++) { // TRC02 packet is 32 bits + 1 bit crc
|
||||
// read data bit
|
||||
fdatabit = fsendbuff & fdatamask; // Get most left bit
|
||||
fsendbuff = (fsendbuff << 1); // Shift left
|
||||
if (fdatabit != fdatamask) { // Write 0
|
||||
digitalWrite(PIN_RF_TX_DATA, LOW);
|
||||
delayMicroseconds(fpulse);
|
||||
digitalWrite(PIN_RF_TX_DATA, HIGH);
|
||||
delayMicroseconds(fpulse);
|
||||
crc += crc^0;
|
||||
} else { // Write 1
|
||||
digitalWrite(PIN_RF_TX_DATA, HIGH);
|
||||
delayMicroseconds(fpulse);
|
||||
digitalWrite(PIN_RF_TX_DATA, LOW);
|
||||
delayMicroseconds(fpulse);
|
||||
crc += crc^1;
|
||||
}
|
||||
}
|
||||
if (crc==1) { // crc pulse
|
||||
delayMicroseconds(fpulse);
|
||||
digitalWrite(PIN_RF_TX_DATA, LOW);
|
||||
delayMicroseconds(fpulse);
|
||||
digitalWrite(PIN_RF_TX_DATA, HIGH);
|
||||
delayMicroseconds(fpulse);
|
||||
} else {
|
||||
delayMicroseconds(fpulse);
|
||||
digitalWrite(PIN_RF_TX_DATA, HIGH);
|
||||
delayMicroseconds(fpulse);
|
||||
digitalWrite(PIN_RF_TX_DATA, LOW);
|
||||
delayMicroseconds(fpulse);
|
||||
}
|
||||
}
|
||||
delayMicroseconds(TRANSMITTER_STABLE_DELAY); // short delay to let the transmitter become stable (Note: Aurel RTX MID needs 500µS/0,5ms)
|
||||
digitalWrite(PIN_RF_TX_VCC,LOW); // Turn thew 433Mhz transmitter off
|
||||
digitalWrite(PIN_RF_RX_VCC,HIGH); // Turn the 433Mhz receiver on
|
||||
RFLinkHW();
|
||||
}
|
||||
#endif //PLUGIN_TX_010
|
|
@ -0,0 +1,444 @@
|
|||
//#######################################################################################################
|
||||
//## This Plugin is only for use with the RFLink software package ##
|
||||
//## Plugin-11 Home Confort Smart Home - TEL-010 ##
|
||||
//#######################################################################################################
|
||||
/*********************************************************************************************\
|
||||
* Decodes signals from a Home Confort Smart Home - TEL-010
|
||||
* http://idk.home-confort.net/divers/t%C3%A9l%C3%A9commande-rf-pour-produits-smart-home
|
||||
*
|
||||
* Author : StuntTeam, François Pasteau
|
||||
* 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!
|
||||
*********************************************************************************************
|
||||
* Changelog: v1.0 initial release
|
||||
*********************************************************************************************
|
||||
* Technical information:
|
||||
* Decodes signals from Home Confort Smart Home - TEL-010 devices
|
||||
* --------------------------------------------------------------------------------------------
|
||||
* _Byte 0_ _Byte 1_ _Byte 2_ _Byte 3_ _Byte 4_ _Byte 5_ _Bits_
|
||||
* AAAAAAAA BBBBBBBB CCCDDDDD EEEEEEEE FFFFFFFF GGHHHHHH II
|
||||
* 11111111 11111111 11100010 00000000 00000000 10000001 00 Type 1 (no address, using A1-D4)
|
||||
* 00110110 10100100 01111010 00000000 00000000 10000001 00 Type 2 (using 19 bit? address and button number 1-?
|
||||
*
|
||||
* A = Address? (19 bits?)
|
||||
* B = Address? (19 bits?)
|
||||
* C = Address? (19 bits?)
|
||||
* D = Command bits (see below)
|
||||
* E = verification bytes?, Always 0x00? => possibly reserved for future use or other device types
|
||||
* F = verification bytes?, Always 0x00? => possibly reserved for future use or other device types
|
||||
* G = Command bits (see below)
|
||||
* H = always '000001' ?
|
||||
* I = Stop bits?, Always '00'
|
||||
*
|
||||
* D & G explanation:
|
||||
* DDDDD GG
|
||||
* 11233 45
|
||||
* 00000 00
|
||||
11010 10 D3
|
||||
* 1=switch setting 00=A 10=B 01=C 11=D
|
||||
* 2=group indicator 1=group command
|
||||
* 3=button number 00=1 01=2 10=3 11=4
|
||||
* 4=command 0=off, 1=on
|
||||
* 5=group indicator 1=group command
|
||||
* ------------
|
||||
* 101010101010101010101010101010101010100101011001010101010101010101010101010101011001010101010110 00
|
||||
* 111111111111111111100010000000000000000010000001 00 A3 on
|
||||
* 20;17;DEBUG;Pulses=100;Pulses(uSec)=
|
||||
* 2675,200,600,200,600,700,100,700,100,200,600,700,100,700,100,200,600,700,100,225,600,725,75,225,600,225,575,725,75,225,
|
||||
* 575,225,575,225,575,725,75,725,75,725,75,725,75,225,575,725,75,225,575,225,575,225,575,225,575,225,575,250,575,250,
|
||||
* 575,250,575,250,575,250,550,250,550,250,550,250,550,250,550,250,550,250,550,250,575,725,75,250,550,250,550,250,550,250,
|
||||
* 550,250,550,250,550,750,50,250,50; =99
|
||||
*
|
||||
* 2675,200,600,200,600,700,100,700,100,200,600,700,100,700,100,200,600,700,100,225,600,725,75,225,600,225,575,725,75,225,575,225,575,225,575,725,75,725,75,725,75,725,75,225,575,725,75,225,575,225,575,225,575,225,575,225,575,250,575,250,575,250,575,250,575,250,550,250,550,250,550,250,550,250,550,250,550,250,550,250,575,725,75,250,550,250,550,250,550,250,550,250,550,250,550,750,50,250,50
|
||||
\*********************************************************************************************/
|
||||
#define HC_PULSECOUNT 100
|
||||
|
||||
#ifdef PLUGIN_011
|
||||
boolean Plugin_011(byte function, char *string) {
|
||||
if (RawSignal.Number != HC_PULSECOUNT ) return false;
|
||||
if (RawSignal.Pulses[1]*RawSignal.Multiply < 2000) return false; // First (start) pulse needs to be long
|
||||
|
||||
unsigned long bitstream1=0; // holds first 24 bits
|
||||
unsigned long bitstream2=0; // holds last 26 bits
|
||||
byte bitcounter=0; // counts number of received bits (converted from pulses)
|
||||
byte command=0;
|
||||
byte channel=0;
|
||||
byte subchan=0;
|
||||
byte group=0;
|
||||
//==================================================================================
|
||||
for(int x=2;x < HC_PULSECOUNT-2;x+=2) { // get bytes
|
||||
if (RawSignal.Pulses[x]*RawSignal.Multiply > 500) { // long pulse
|
||||
if (RawSignal.Pulses[x]*RawSignal.Multiply > 800) return false; // Pulse range check
|
||||
if (RawSignal.Pulses[x+1]*RawSignal.Multiply > 400) return false; // Manchester check
|
||||
if (bitcounter < 24) {
|
||||
bitstream1 = (bitstream1 << 1) | 0x1;
|
||||
} else {
|
||||
bitstream2 = (bitstream2 << 1) | 0x1;
|
||||
}
|
||||
bitcounter++; // only need to count the first 10 bits
|
||||
} else { // short pulse
|
||||
if (RawSignal.Pulses[x]*RawSignal.Multiply > 300) return false; // pulse range check
|
||||
if (RawSignal.Pulses[x+1]*RawSignal.Multiply < 400) return false; // Manchester check
|
||||
if (bitcounter < 24) {
|
||||
bitstream1 = (bitstream1 << 1);
|
||||
} else {
|
||||
bitstream2 = (bitstream2 << 1);
|
||||
}
|
||||
bitcounter++; // only need to count the first 10 bits
|
||||
}
|
||||
if (bitcounter > 50) break;
|
||||
}
|
||||
if (RawSignal.Pulses[98]*RawSignal.Multiply > 300) return false; // pulse range check, last two pulses should be short
|
||||
if (RawSignal.Pulses[99]*RawSignal.Multiply > 300) return false; // pulse range check
|
||||
//==================================================================================
|
||||
// first perform a check to make sure the packet is valid
|
||||
byte tempbyte=(bitstream2 >>8) & 0xff;
|
||||
if (tempbyte != 0x0) return false; // always 0x00?
|
||||
tempbyte=(bitstream2 >>16) & 0xff;
|
||||
if (tempbyte != 0x0) return false; // always 0x00?
|
||||
tempbyte=(bitstream2) & 0x3f;
|
||||
if (tempbyte != 0x01) return false; // low 6 bits are always '000001'?
|
||||
//==================================================================================
|
||||
// Prevent repeating signals from showing up
|
||||
//==================================================================================
|
||||
if(SignalHash!=SignalHashPrevious || ((RepeatingTimer+1500)<millis()) || SignalCRC != bitstream2 ) {
|
||||
// not seen the RF packet recently
|
||||
SignalCRC=bitstream2;
|
||||
} else {
|
||||
// already seen the RF packet recently
|
||||
return true;
|
||||
}
|
||||
//==================================================================================
|
||||
// now process the command / switch settings
|
||||
//==================================================================================
|
||||
tempbyte=(bitstream1 >> 3) & 0x03; // determine switch setting (a/b/c/d)
|
||||
channel=0x41;
|
||||
if (tempbyte==2) channel=0x42;
|
||||
if (tempbyte==1) channel=0x43;
|
||||
if (tempbyte==3) channel=0x44;
|
||||
|
||||
subchan=((bitstream1)&0x03)+1; // determine button number
|
||||
|
||||
command=(bitstream2 >> 7) & 0x01; // on/off command
|
||||
group=(bitstream2 >> 6) & 0x01; // group setting
|
||||
|
||||
bitstream1=bitstream1 >> 5;
|
||||
//==================================================================================
|
||||
// Output
|
||||
// ----------------------------------
|
||||
sprintf(pbuffer, "20;%02X;", PKSequenceNumber++); // Node and packet number
|
||||
Serial.print( pbuffer );
|
||||
Serial.print(F("HomeConfort;")); // Label
|
||||
sprintf(pbuffer, "ID=%06lx;",((bitstream1) &0xffffff) ); // ID
|
||||
Serial.print( pbuffer );
|
||||
sprintf(pbuffer, "SWITCH=%c%d;", channel,subchan);
|
||||
Serial.print( pbuffer );
|
||||
Serial.print(F("CMD="));
|
||||
if (group==1) Serial.print(F("ALL"));
|
||||
if (command==0) Serial.print(F("OFF;"));
|
||||
if (command==1) Serial.print(F("ON;"));
|
||||
Serial.println();
|
||||
//==================================================================================
|
||||
RawSignal.Repeats=true; // suppress repeats of the same RF packet
|
||||
RawSignal.Number=0;
|
||||
return true;
|
||||
}
|
||||
#endif // PLUGIN_011
|
||||
|
||||
#ifdef PLUGIN_TX_011
|
||||
void HomeConfort_Send(unsigned long bitstream1, unsigned long bitstream2);
|
||||
|
||||
boolean PluginTX_011(byte function, char *string) {
|
||||
boolean success=false;
|
||||
//10;HomeConfort;01b523;D3;ON;
|
||||
//0123456789012345678901234567
|
||||
if (strncasecmp(InputBuffer_Serial+3,"HomeConfort;",12) == 0) { // KAKU Command eg.
|
||||
if (InputBuffer_Serial[21] != ';') return success;
|
||||
|
||||
InputBuffer_Serial[13]=0x30;
|
||||
InputBuffer_Serial[14]=0x78; // Get address from hexadecimal value
|
||||
InputBuffer_Serial[21]=0x00; // Get address from hexadecimal value
|
||||
|
||||
unsigned long bitstream1=0L; // First Main placeholder
|
||||
unsigned long bitstream2=0L; // Second Main placeholder
|
||||
byte Home=0; // channel A..D
|
||||
byte Address=0; // subchannel 1..5
|
||||
byte c;
|
||||
byte x=22; // pointer
|
||||
// -------------------------------
|
||||
bitstream1=str2int(InputBuffer_Serial+13); // Address (first 19 bits)
|
||||
// -------------------------------
|
||||
while((c=tolower(InputBuffer_Serial[x++]))!=';') {
|
||||
if(c>='0' && c<='9'){Address=Address+c-'0';} // Home 0..9
|
||||
if(c>='a' && c<='d'){Home=c-'a';} // Address a..d
|
||||
}
|
||||
// -------------------------------
|
||||
// prepare bitstream1
|
||||
// -------------------------------
|
||||
bitstream1 = bitstream1 << 5; // make space for first 5 command bits
|
||||
Address--; // 1..4 to 0..3
|
||||
Address=Address & 0x03; // only accept 2 bits for the button number part
|
||||
bitstream1=bitstream1+Address;
|
||||
|
||||
if (Home == 0) c=0; // A
|
||||
if (Home == 1) c=2; // B
|
||||
if (Home == 2) c=1; // C
|
||||
if (Home == 3) c=3; // D
|
||||
Home=c << 3; // shift left for the right position
|
||||
bitstream1=bitstream1+Home;
|
||||
// -------------------------------
|
||||
// prepare bitsrteam2
|
||||
c=0;
|
||||
c = str2cmd(InputBuffer_Serial+x); // ON/OFF command
|
||||
bitstream2=1; // value off
|
||||
if (c == VALUE_ON) {
|
||||
bitstream2=0x81; // value on
|
||||
} else {
|
||||
if (c == VALUE_ALLOFF) {
|
||||
bitstream2=0x41;
|
||||
bitstream1=bitstream1+4; // set group
|
||||
} else
|
||||
if (c == VALUE_ALLON) {
|
||||
bitstream2=0xc1;
|
||||
bitstream1=bitstream1+4; // set group
|
||||
}
|
||||
}
|
||||
// -------------------------------
|
||||
HomeConfort_Send(bitstream1,bitstream2); // bitstream to send
|
||||
success=true;
|
||||
}
|
||||
return success;
|
||||
}
|
||||
/*
|
||||
void HomeConfort_Send(unsigned long data1, unsigned long data2) {
|
||||
int fpulse = 270; // Pulse width in microseconds
|
||||
int fpulse2 = 710; // Pulse width in microseconds
|
||||
int fretrans = 10; // Number of code retransmissions
|
||||
|
||||
unsigned long bitstream1 = 0L;
|
||||
unsigned long bitstream2 = 0L;
|
||||
// prepare data to send
|
||||
for (unsigned short i=0; i<24; i++) { // reverse data bits
|
||||
bitstream1<<=1;
|
||||
bitstream1|=(data1 & B1);
|
||||
data1>>=1;
|
||||
}
|
||||
for (unsigned short i=0; i<24; i++) { // reverse data bits
|
||||
bitstream2<<=1;
|
||||
bitstream2|=(data2 & B1);
|
||||
data2>>=1;
|
||||
}
|
||||
// -------------------------------
|
||||
// bitstream1 holds first 24 bits of the RF data, bitstream2 holds last 24 bits of the RF data
|
||||
// -------------------------------
|
||||
// Prepare transmit
|
||||
digitalWrite(PIN_RF_RX_VCC,LOW); // Turn off power to the RF receiver
|
||||
digitalWrite(PIN_RF_TX_VCC,HIGH); // Enable the 433Mhz transmitter
|
||||
delayMicroseconds(TRANSMITTER_STABLE_DELAY); // short delay to let the transmitter become stable (Note: Aurel RTX MID needs 500µS/0,5ms)
|
||||
// send bits
|
||||
for (int nRepeat = 0; nRepeat <= fretrans; nRepeat++) {
|
||||
data1=bitstream1;
|
||||
data2=bitstream2;
|
||||
digitalWrite(PIN_RF_TX_DATA, HIGH);
|
||||
delayMicroseconds(fpulse*10 + (fpulse >> 1)); //335*9=3015 //270*10=2700
|
||||
for (unsigned short i=0; i<24; i++) {
|
||||
switch (data1 & B1) {
|
||||
case 0:
|
||||
digitalWrite(PIN_RF_TX_DATA, LOW);
|
||||
delayMicroseconds(fpulse * 1);
|
||||
digitalWrite(PIN_RF_TX_DATA, HIGH);
|
||||
delayMicroseconds(fpulse2 * 1);
|
||||
break;
|
||||
case 1:
|
||||
digitalWrite(PIN_RF_TX_DATA, LOW);
|
||||
delayMicroseconds(fpulse2 * 1);
|
||||
digitalWrite(PIN_RF_TX_DATA, HIGH);
|
||||
delayMicroseconds(fpulse * 1);
|
||||
break;
|
||||
}
|
||||
//Next bit
|
||||
data1>>=1;
|
||||
}
|
||||
for (unsigned short i=0; i<24; i++) {
|
||||
switch (data2 & B1) {
|
||||
case 0:
|
||||
digitalWrite(PIN_RF_TX_DATA, LOW);
|
||||
delayMicroseconds(fpulse * 1);
|
||||
digitalWrite(PIN_RF_TX_DATA, HIGH);
|
||||
delayMicroseconds(fpulse2 * 1); // 335*3=1005 260*5=1300 260*4=1040
|
||||
break;
|
||||
case 1:
|
||||
digitalWrite(PIN_RF_TX_DATA, LOW);
|
||||
delayMicroseconds(fpulse2 * 1);
|
||||
digitalWrite(PIN_RF_TX_DATA, HIGH);
|
||||
delayMicroseconds(fpulse * 1);
|
||||
break;
|
||||
}
|
||||
//Next bit
|
||||
data2>>=1;
|
||||
}
|
||||
//Send termination/synchronisation-signal.
|
||||
//digitalWrite(PIN_RF_TX_DATA, HIGH);
|
||||
//delayMicroseconds(fpulse);
|
||||
digitalWrite(PIN_RF_TX_DATA, LOW);
|
||||
delayMicroseconds(fpulse * 27);
|
||||
|
||||
//RawSignal.Pulses[98]=300/RawSignal.Multiply;
|
||||
//RawSignal.Pulses[99]=175/RawSignal.Multiply;
|
||||
//RawSignal.Delay=125; // Delay between RF packets
|
||||
|
||||
}
|
||||
// End transmit
|
||||
delayMicroseconds(TRANSMITTER_STABLE_DELAY); // short delay to let the transmitter become stable (Note: Aurel RTX MID needs 500µS/0,5ms)
|
||||
digitalWrite(PIN_RF_TX_VCC,LOW); // Turn thew 433Mhz transmitter off
|
||||
digitalWrite(PIN_RF_RX_VCC,HIGH); // Turn the 433Mhz receiver on
|
||||
RFLinkHW();
|
||||
}
|
||||
|
||||
void HomeConfort_Send(unsigned long data1, unsigned long data2) {
|
||||
int fpulse = 270; // Pulse width in microseconds
|
||||
int fpulse2 = 710; // Pulse width in microseconds
|
||||
int fretrans = 10; // Number of code retransmissions
|
||||
|
||||
unsigned long bitstream1 = 0L;
|
||||
unsigned long bitstream2 = 0L;
|
||||
// prepare data to send
|
||||
for (unsigned short i=0; i<24; i++) { // reverse data bits
|
||||
bitstream1<<=1;
|
||||
bitstream1|=(data1 & B1);
|
||||
data1>>=1;
|
||||
}
|
||||
for (unsigned short i=0; i<24; i++) { // reverse data bits
|
||||
bitstream2<<=1;
|
||||
bitstream2|=(data2 & B1);
|
||||
data2>>=1;
|
||||
}
|
||||
// -------------------------------
|
||||
// bitstream1 holds first 24 bits of the RF data, bitstream2 holds last 24 bits of the RF data
|
||||
// -------------------------------
|
||||
// Prepare transmit
|
||||
digitalWrite(PIN_RF_RX_VCC,LOW); // Turn off power to the RF receiver
|
||||
digitalWrite(PIN_RF_TX_VCC,HIGH); // Enable the 433Mhz transmitter
|
||||
delayMicroseconds(TRANSMITTER_STABLE_DELAY); // short delay to let the transmitter become stable (Note: Aurel RTX MID needs 500µS/0,5ms)
|
||||
// send bits
|
||||
for (int nRepeat = 0; nRepeat <= fretrans; nRepeat++) {
|
||||
data1=bitstream1;
|
||||
data2=bitstream2;
|
||||
digitalWrite(PIN_RF_TX_DATA, HIGH);
|
||||
//delayMicroseconds(fpulse); //335
|
||||
delayMicroseconds(335);
|
||||
digitalWrite(PIN_RF_TX_DATA, LOW);
|
||||
delayMicroseconds(fpulse*10 + (fpulse >> 1)); //335*9=3015 //270*10=2700
|
||||
for (unsigned short i=0; i<24; i++) {
|
||||
switch (data1 & B1) {
|
||||
case 0:
|
||||
digitalWrite(PIN_RF_TX_DATA, HIGH);
|
||||
delayMicroseconds(fpulse * 1);
|
||||
digitalWrite(PIN_RF_TX_DATA, LOW);
|
||||
delayMicroseconds(fpulse2 * 1);
|
||||
break;
|
||||
case 1:
|
||||
digitalWrite(PIN_RF_TX_DATA, HIGH);
|
||||
delayMicroseconds(fpulse2 * 1);
|
||||
digitalWrite(PIN_RF_TX_DATA, LOW);
|
||||
delayMicroseconds(fpulse * 1);
|
||||
break;
|
||||
}
|
||||
//Next bit
|
||||
data1>>=1;
|
||||
}
|
||||
for (unsigned short i=0; i<24; i++) {
|
||||
switch (data2 & B1) {
|
||||
case 0:
|
||||
digitalWrite(PIN_RF_TX_DATA, HIGH);
|
||||
delayMicroseconds(fpulse * 1);
|
||||
digitalWrite(PIN_RF_TX_DATA, LOW);
|
||||
delayMicroseconds(fpulse2 * 1); // 335*3=1005 260*5=1300 260*4=1040
|
||||
break;
|
||||
case 1:
|
||||
digitalWrite(PIN_RF_TX_DATA, HIGH);
|
||||
delayMicroseconds(fpulse2 * 1);
|
||||
digitalWrite(PIN_RF_TX_DATA, LOW);
|
||||
delayMicroseconds(fpulse * 1);
|
||||
break;
|
||||
}
|
||||
//Next bit
|
||||
data2>>=1;
|
||||
}
|
||||
//Send termination/synchronisation-signal.
|
||||
digitalWrite(PIN_RF_TX_DATA, HIGH);
|
||||
delayMicroseconds(fpulse);
|
||||
digitalWrite(PIN_RF_TX_DATA, LOW);
|
||||
delayMicroseconds(fpulse * 27);
|
||||
|
||||
//RawSignal.Pulses[98]=300/RawSignal.Multiply;
|
||||
//RawSignal.Pulses[99]=175/RawSignal.Multiply;
|
||||
//RawSignal.Delay=125; // Delay between RF packets
|
||||
|
||||
}
|
||||
// End transmit
|
||||
delayMicroseconds(TRANSMITTER_STABLE_DELAY); // short delay to let the transmitter become stable (Note: Aurel RTX MID needs 500µS/0,5ms)
|
||||
digitalWrite(PIN_RF_TX_VCC,LOW); // Turn thew 433Mhz transmitter off
|
||||
digitalWrite(PIN_RF_RX_VCC,HIGH); // Turn the 433Mhz receiver on
|
||||
RFLinkHW();
|
||||
}
|
||||
*/
|
||||
/*
|
||||
20;E4;DEBUG;Pulses=511;Pulses(uSec)=
|
||||
330,2760,180,600,180,600,630,180,630,180,180,600,630,180,630,150,210,600,630,150,210,600,630,180,180,600,180,600,630,180,180,600,180,600,180,600,630,180,630,180,630,180,630,180,180,600,630,180,180,600,180,600,180,600,180,600,180,600,180,600,180,600,180,600,180,600,180,600,180,600,180,600,180,600,180,600,180,600,180,600,180,600,630,180,180,600,180,600,180,600,180,600,210,600,210,600,630,150,210,180,
|
||||
270,2760,180,600,180,600,630,180,630,180,180,600,630,180,630,180,180,600,630,180,180,600,630,180,180,600,180,600,630,180,180,600,180,600,180,600,630,180,630,180,630,180,630,180,180,600,630,150,210,600,210,600,210,600,210,600,180,600,180,600,180,600,180,600,180,600,180,600,180,630,180,630,180,630,180,630,180,630,180,600,180,600,630,180,180,600,180,600,180,600,180,600,180,600,180,600,630,180,180,150,
|
||||
270,2760,210,600,210,600,630,150,630,150,210,600,630,180,630,180,180,600,630,180,180,600,630,180,180,630,180,630,630,180,180,630,180,630,180,630,630,180,630,180,630,180,630,180,180,600,630,180,180,600,180,600,180,600,180,600,180,600,180,600,180,600,180,600,180,600,180,600,180,600,180,600,180,600,180,600,180,600,180,600,210,600,630,150,210,600,210,600,210,600,210,600,180,600,180,600,630,180,180,180,270,2760,180,600,180,600,630,180,630,180,180,600,630,180,630,180,180,600,630,180,180,600,630,180,180,600,180,600,630,180,180,600,180,600,210,600,630,150,630,150,630,150,630,150,210,600,630,180,180,600,180,600,180,600,180,600,180,630,180,630,180,630,180,630,180,630,180,630,180,630,180,600,180,600,180,600,180,600,180,600,180,600,630,180,180,600,180,600,180,600,180,600,180,600,180,600,630,180,180,180,270,2760,210,600,180,600,630,180,630,180,180,630,630,180,630,180,180,630,630,180,180,630,630,180,180,630,180,600,630,180,180,600,180,600,180,600,630,180,630,180,630,180,630,180,180,600,630,180,180,600,180,600,180,600,180,600,180,600,180,600,180,600,180,600,180,600,210,600,210,600,210,600,210,600,210,600,210,600,210,600,210,600,630,180,180,600,180,630,180,630,180,630,180,630,180,630,630,180,180,180,270,2760,180,600,180,600,630,180,630,180,180;
|
||||
|
||||
|
||||
20;CA;DEBUG;Pulses=100;Pulses(uSec)=
|
||||
2490,180,630,150,630,600,180,600,180,150,630,600,180,600,180,150,630,630,180,150,630,630,180,150,630,150,630,630,180,150,630,150,630,150,630,630,180,600,180,600,180,600,180,150,630,600,180,150,630,150,630,150,630,150,630,150,630,150,630,150,630,150,630,150,630,150,630,150,630,150,630,150,630,150,630,150,630,150,630,150,630,150,630,150,630,150,630,150,630,150,630,150,630,150,630,630,180,180,60,6990;
|
||||
*/
|
||||
|
||||
#define PLUGIN_011_RFLOW 270 // 300
|
||||
#define PLUGIN_011_RFHIGH 720 // 800
|
||||
|
||||
void HomeConfort_Send(unsigned long bitstream1, unsigned long bitstream2) {
|
||||
RawSignal.Repeats=8; // Number of RF packet retransmits
|
||||
RawSignal.Delay=125; // Delay between RF packets
|
||||
RawSignal.Number=100; // Length
|
||||
|
||||
uint32_t fdatabit;
|
||||
uint32_t fdatamask = 0x800000;
|
||||
// -------------------------------
|
||||
// bitstream1 holds first 24 bits of the RF data, bitstream2 holds last 24 bits of the RF data
|
||||
// -------------------------------
|
||||
RawSignal.Pulses[1]=2600/RawSignal.Multiply;
|
||||
|
||||
for (byte i=2; i<103; i=i+2) {
|
||||
if (i<50) { // first 24 bits
|
||||
fdatabit = bitstream1 & fdatamask; // Get most left bit
|
||||
bitstream1 = (bitstream1 << 1); // Shift left
|
||||
|
||||
if (fdatabit != fdatamask) { // Write 0
|
||||
RawSignal.Pulses[i] = PLUGIN_011_RFLOW/RawSignal.Multiply;
|
||||
RawSignal.Pulses[i+1]= PLUGIN_011_RFHIGH/RawSignal.Multiply;
|
||||
} else { // Write 1
|
||||
RawSignal.Pulses[i] = PLUGIN_011_RFHIGH/RawSignal.Multiply;
|
||||
RawSignal.Pulses[i+1]= PLUGIN_011_RFLOW/RawSignal.Multiply;
|
||||
}
|
||||
} else {
|
||||
fdatabit = bitstream2 & fdatamask; // Get most left bit
|
||||
bitstream2 = (bitstream2 << 1); // Shift left
|
||||
|
||||
if (fdatabit != fdatamask) { // Write 0
|
||||
RawSignal.Pulses[i] = PLUGIN_011_RFLOW/RawSignal.Multiply;
|
||||
RawSignal.Pulses[i+1]= PLUGIN_011_RFHIGH/RawSignal.Multiply;
|
||||
} else { // Write 1
|
||||
RawSignal.Pulses[i] = PLUGIN_011_RFHIGH/RawSignal.Multiply;
|
||||
RawSignal.Pulses[i+1]= PLUGIN_011_RFLOW/RawSignal.Multiply;
|
||||
}
|
||||
}
|
||||
}
|
||||
RawSignal.Pulses[98]=300/RawSignal.Multiply;
|
||||
RawSignal.Pulses[99]=175/RawSignal.Multiply;
|
||||
|
||||
RawSendRF();
|
||||
}
|
||||
#endif // PLUGIN_TX_011
|
||||
|
|
@ -0,0 +1,309 @@
|
|||
//#######################################################################################################
|
||||
//## This Plugin is only for use with the RFLink software package ##
|
||||
//## Plugin-03: FA500R ##
|
||||
//#######################################################################################################
|
||||
/*********************************************************************************************\
|
||||
* This plugin takes care of sending and receiving the Elro Flamingo FA500 protocol.
|
||||
* Also works with compatible devices like the Mumbi M-FS300 and Silvercrest 91210/60494 RCS AAA3680, Unitec eim 821/art.48111
|
||||
*
|
||||
* Author : StuntTeam
|
||||
* 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!
|
||||
***********************************************************************************************
|
||||
* Incoming event: "FA500 <adres>,<On | Off>
|
||||
* Send : "FA500Send <Adres>, <On | Off>
|
||||
*
|
||||
* Address = A/B/C/D matching the remote control buttons.
|
||||
***********************************************************************************************
|
||||
* Technical information:
|
||||
* The FA500R remote control sends 3 different protocols.
|
||||
* 4 x Method 1 - 28 bit code
|
||||
* 6 x method 2 - AC compatible
|
||||
* 5 x method 3 - 24/12 bit code
|
||||
* It appears that the FA500S is only capable to react to the first method. So this has to be used to switch sockets
|
||||
* Nodo can only distinguish the 3rd method properly. Method 1 and 2 have to be pulled apart first which
|
||||
* is done via plugin 001.
|
||||
*
|
||||
* Device types:
|
||||
* Elro FA500S Flamingo Switch
|
||||
* Elro FA500DSS Flamingo Dimmer
|
||||
* Elro FA500WD Flamingo Outdoor
|
||||
* Elro FA500R Flamingo Remote Control
|
||||
*
|
||||
* PCB Markings:
|
||||
* 50027.01B FLF-130105
|
||||
* KT50039.01A FLF-13-06-03 Chip marking: S007V0.1
|
||||
* KT50040.01A FLF-13-06-04
|
||||
*
|
||||
* http://forum.arduino.cc/index.php?topic=202556.0
|
||||
*
|
||||
* Sample:
|
||||
* 20;60;DEBUG;Pulses=24;Pulses(uSec)=325,800,275,800,825,225,275,800,275,825,275,800,825,225,275,800,825,225,275,800,275,800,275;
|
||||
* 20;61;DEBUG;Pulses=58;Pulses(uSec)=200,875,800,250,800,225,200,875,200,875,800,250,200,875,200,875,800,250,200,875,200,875,200,875,200,875,825,250,200,875,200,875,200,875,825,250,200,875,825,250,200,875,200,875,200,875,825,225,825,250,200,875,825,250,200,875,150;
|
||||
|
||||
* 20;3E;DEBUG;Pulses=58;Pulses(uSec)=300,950,225,950,875,275,225,950,225,950,875,275,225,950,225,950,875,275,875,275,225,950,875,275,225,950,225,950,875,275,875,275,225,950,225,950,225,950,875,275,875,275,200,950,225,950,875,275,875,275,225,950,875,275,225,950,225;
|
||||
* 20;3F;DEBUG;Pulses=64;Pulses(uSec)=525,250,200,900,200,4900,200,900,200,900,875,275,225,950,225,950,875,275,225,950,225,950,875,275,875,275,225,950,900,250,225,950,225,950,875,250,875,275,225,950,225,950,225,950,900,275,875,275,225,950,225,950,875,275,875,275,225,950,875,250,225,950,225;
|
||||
* 20;40;DEBUG;Pulses=130;Pulses(uSec)=225,175,150,1250,150,200,150,1250,150,200,150,1250,150,200,150,1250,150,200,150,1275,150,200,150,1300,150,200,150,1300,150,200,150,1300,150,200,150,1300,150,1275,150,225,150,200,150,1300,150,200,150,1300,150,200,150,1300,150,1275,150,225,150,1275,150,225,150,200,150,1300,150,1275,150,225,150,1275,150,225,150,200,150,1300,150,200,150,1300,150,200,150,1300,150,200,150,1300,150,200,150,1300,150,200,150,1300,150,200,150,1300,150,200,150,1300,150,200,150,1300,150,200,150,1300,150,200,150,1300,150,200,150,1300,150,200,150,1300,150,1275,150,200,150;
|
||||
* 20;41;DEBUG;Pulses=126;Pulses(uSec)=225,200,125,1250,150,200,150,1250,150,175,150,1250,150,175,150,1300,150,200,150,1300,150,200,150,1300,150,200,150,1300,150,200,150,1300,150,1300,150,225,150,200,150,1300,150,200,150,1300,150,200,150,1300,150,1275,150,200,150,1275,150,225,150,200,150,1300,150,1275,150,225,150,1275,150,225,150,200,150,1300,150,200,150,1300,150,200,150,1300,150,200,150,1300,150,200,150,1300,150,200,150,1300,150,200,150,1300,150,200,150,1300,150,200,150,1300,150,200,150,1300,150,200,150,1300,150,200,150,1300,150,200,150,1300,150,1275,150,200,150;
|
||||
* 20;42;DEBUG;Pulses=116;Pulses(uSec)=175,1275,150,1225,150,200,150,200,150,200,150,1250,150,1250,150,1300,150,1275,150,200,150,200,150,200,150,1275,150,1300,150,1300,150,1300,150,225,150,1300,150,225,150,225,150,1300,150,1300,150,1300,150,200,150,1300,150,200,150,1300,150,1275,150,225,150,1275,150,225,150,200,150,225,150,1300,150,1300,150,225,150,1300,150,200,150,200,150,200,150,1275,150,1300,150,1300,150,1300,150,200,150,200,150,200,150,1300,150,1300,150,1300,150,1300,150,200,150,200,150,1275,150,225,150,1275,150,1300,150;
|
||||
|
||||
20;CC;DEBUG;Pulses=58;Pulses(uSec)=300,950,225,950,900,275,225,950,225,950,875,275,225,950,225,950,225,950,900,275,875,275,225,950,225,950,225,950,225,950,225,950,225,950,225,950,225,950,225,950,875,275,225,950,225,950,225,950,875,275,875,275,875,250,225,950,225;
|
||||
20;CD;DEBUG;Pulses=64;Pulses(uSec)=525,250,200,900,200,4900,225,900,200,925,875,275,225,950,225,950,875,275,225,950,225,950,225,950,900,275,875,275,225,950,225,950,225,950,225,950,225,950,225,950,225,950,225,950,225,950,875,275,225,950,225,950,225,950,875,275,875,275,900,250,225,950,225;
|
||||
20;CE;DEBUG;Pulses=130;Pulses(uSec)=225,200,150,1250,150,200,150,1250,150,200,150,1250,150,200,150,1250,150,200,150,1300,150,200,150,1300,150,200,150,1300,150,200,150,1300,150,200,150,1300,150,1275,150,200,150,200,150,1300,150,200,175,1300,150,200,150,1300,150,1275,150,200,150,1275,150,200,150,200,150,1300,150,1275,150,200,150,1275,150,200,150,200,150,1300,150,200,175,1300,150,200,150,1300,150,200,150,1300,150,200,150,1300,150,200,150,1300,150,200,150,1300,150,200,150,1300,150,200,150,1300,150,200,150,1300,150,200,150,1300,150,200,150,1300,150,200,150,1300,150,1275,150,200,150;
|
||||
20;CF;DEBUG;Pulses=126;Pulses(uSec)=225,200,150,1250,150,200,150,1250,150,200,150,1250,150,200,150,1300,150,200,150,1300,150,200,150,1300,150,200,150,1300,150,200,150,1300,150,1275,150,200,150,200,150,1300,150,200,150,1300,150,200,150,1300,150,1275,150,200,150,1275,150,200,150,200,175,1300,150,1275,150,200,150,1300,150,200,150,200,150,1300,150,200,150,1300,150,200,150,1275,150,200,150,1300,150,200,150,1300,150,200,150,1300,150,200,150,1300,150,200,150,1300,150,200,150,1300,150,200,150,1300,150,200,150,1300,150,200,150,1300,150,200,150,1300,150,1275,150,200,150;
|
||||
20;D0;DEBUG;Pulses=116;Pulses(uSec)=275,1250,150,1250,150,200,150,200,150,200,150,1250,150,1250,150,1300,150,1300,150,200,150,200,150,200,150,1300,150,1275,150,1300,150,1300,150,200,150,1300,150,200,150,200,150,1300,150,1300,150,1275,150,200,150,1275,150,225,150,1275,150,1300,150,225,150,1300,150,200,150,200,150,225,150,1300,150,1300,150,200,175,1275,175,200,150,200,150,200,150,1300,150,1275,150,1300,150,1275,175,200,150,200,150,200,150,1300,150,1300,150,1300,150,1275,150,200,150,200,175,1300,150,200,150,1300,150,1300,150;
|
||||
20;D1;HomeEasy;ID=7a75a347;SWITCH=0b;CMD=ALLON;
|
||||
20;D2;DEBUG;Pulses=50;Pulses(uSec)=3200,875,300,875,300,875,300,875,300,875,300,875,300,875,300,875,300,875,300,875,300,875,300,900,275,875,300,875,300,875,925,250,300,875,300,875,300,875,925,250,300,875,925,250,300,875,300,875,300;
|
||||
20;D3;Kaku;ID=5f;SWITCH=20;CMD=OFF;
|
||||
20;D4;DEBUG;Pulses=50;Pulses(uSec)=3150,875,300,875,300,875,300,875,300,875,300,875,300,875,300,875,300,875,300,875,300,875,300,875,300,875,300,875,300,875,925,250,300,875,300,875,300,875,900,250,300,875,925,250,300,875,300,875,300;
|
||||
20;D5;Kaku;ID=5f;SWITCH=20;CMD=OFF;
|
||||
|
||||
|
||||
20;CC;DEBUG;Pulses=58;Pulses(uSec)=300,950,225,950,900,275,225,950,225,950,875,275,225,950,225,950,225,950,900,275,875,275,225,950,225,950,225,950,225,950,225,950,225,950,225,950,225,950,225,950,875,275,225,950,225,950,225,950,875,275,875,275,875,250,225,950,225;
|
||||
20;86;DEBUG;Pulses=58;Pulses(uSec)=250,4500,225,800,225,800,825,200,225,800,225,800,825,200,225,800,225,800,825,200,825,200,225,800,825,200,225,825,225,800,825,200,825,200,225,800,225,825,225,800,825,200,825,200,225,800,225,825,825,200,825,200,225,800,825,200,225;
|
||||
300,4500,225,800,225,825,825,200,225,800,225,800,825,200,825,200,225,800,825,200,225,800,825,200,825,200,825,200,225,800,825,200,825,200,825,200,225,825,225,800,825,200,825,200,225,800,225,825,225,800,225,800,825,200,825,200,225;
|
||||
00010011010111011100110000110
|
||||
0010010010100011111101011110
|
||||
|
||||
20;D5;DEBUG;Pulses=364;Pulses(uSec)=
|
||||
250,4875,200,900,200,900,875,275,200,900,200,900,875,275,200,900,875,250,225,900,875,275,875,250,225,900,200,925,200,925,200,900,875,250,850,250,225,925,875,250,875,250,225,900,850,275,200,900,875,250,225,900,875,250,875,250,225,900,
|
||||
200,4875,200,900,225,900,850,250,200,900,225,900,850,275,200,900,875,250,225,900,875,275,850,250,200,900,200,900,200,925,200,900,875,250,875,250,200,925,850,250,875,275,200,900,875,275,200,900,875,250,225,900,875,250,850,250,200,900,
|
||||
200,4875,200,900,225,900,875,275,200,925,200,900,875,275,200,900,875,250,225,900,875,275,850,275,200,925,200,900,225,925,200,900,875,250,875,250,225,925,875,250,875,250,225,900,875,275,200,900,850,275,200,900,875,250,850,250,200,900,
|
||||
200,4875,200,900,225,925,850,250,225,900,200,900,850,275,225,900,850,275,200,900,875,275,875,250,200,900,225,900,200,925,200,900,875,250,875,250,225,925,850,250,875,250,225,900,875,250,225,900,875,250,200,900,875,250,875,250,200,925,
|
||||
150,2650,150,200,150,1250,150,200,150,1250,150,200,150,1250,150,200,150,1250,150,200,150,1250,150,200,150,1250,150,200,150,1225,150,200,150,1225,150,200,150,1250,150,1225,150,200,150,200,150,1250,150,200,150,1250,150,200,150,1250,150,1225,150,225,150,1225,150,200,150,200,150,1250,150,1225,150,200,150,1225,150,200,150,200,150,1250,150,200,150,1250,150,200,150,1250,150,200,150,1225,150,200,150,1250,150,200,150,1225,150,200,150,1225,150,200,150,1250,150,200,150,1250,150,1225,150,200,150,200,150,1250,150,200,150,1250,150,200,150,1250,150,1225,150,200,150;
|
||||
|
||||
\*********************************************************************************************/
|
||||
#define FA500RM3_PulseLength 26
|
||||
#define FA500RM1_PulseLength 58
|
||||
#define FA500_PULSEMID 400/RAWSIGNAL_SAMPLE_RATE
|
||||
|
||||
#ifdef PLUGIN_012
|
||||
boolean Plugin_012(byte function, char *string) {
|
||||
if (RawSignal.Number!=(FA500RM3_PulseLength) && RawSignal.Number!=(FA500RM1_PulseLength)) return false;
|
||||
|
||||
byte type=0; // 0=KAKU 1=ITK 2=PT2262
|
||||
byte housecode=0;
|
||||
byte unitcode=0;
|
||||
byte command=0;
|
||||
unsigned long bitstream=0L;
|
||||
unsigned long address=0L;
|
||||
// ==========================================================================
|
||||
if (RawSignal.Number==(FA500RM3_PulseLength) ) {
|
||||
// get all 26pulses =>24 manchester bits => 12 actual bits
|
||||
type=0;
|
||||
for(byte x=2;x <=FA500RM3_PulseLength-2;x+=2) { // Method 3
|
||||
if(RawSignal.Pulses[x] > FA500_PULSEMID) {
|
||||
bitstream = (bitstream << 1) | 0x1;
|
||||
} else {
|
||||
bitstream = (bitstream << 1);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
// get all 58pulses =>28 bits
|
||||
type=1;
|
||||
for(byte x=1;x <=FA500RM1_PulseLength-2;x+=2) { // method 1
|
||||
if(RawSignal.Pulses[x] > FA500_PULSEMID) {
|
||||
bitstream = (bitstream << 1) | 0x1;
|
||||
} else {
|
||||
bitstream = (bitstream << 1);
|
||||
}
|
||||
}
|
||||
}
|
||||
//==================================================================================
|
||||
// perform sanity checks
|
||||
if (bitstream==0) return false; // no bits detected?
|
||||
if (type == 0) {
|
||||
housecode=(((bitstream) >> 8) &0x0f);
|
||||
unitcode=(( bitstream >> 1)& 0x7F);
|
||||
if (unitcode != 0x0A) { // invalid housecode?
|
||||
return false;
|
||||
}
|
||||
address=housecode;
|
||||
command=(bitstream)&1;
|
||||
} else {
|
||||
// 001001 0010100011111101 0111 10
|
||||
// ^^^^^^ ^^
|
||||
address=bitstream;
|
||||
address=address >> 22;
|
||||
address=address << 2;
|
||||
housecode=(bitstream)&3;
|
||||
address=address+housecode;
|
||||
// sort buttons based on first 6 bits and last 2 bits
|
||||
if (address==0x26) { // A On/off
|
||||
housecode=1;
|
||||
} else
|
||||
if (address==0x25) { // B On/off
|
||||
housecode=4;
|
||||
} else
|
||||
if (address==0xe5) { // C On/off
|
||||
housecode=5;
|
||||
} else
|
||||
if (address==0x66) { // D On/off
|
||||
housecode=0;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
command=2; // initialize to "unknown"
|
||||
// Trick: here we use the on/off command from the other packet type as it is not detected in the current packet, it was passed via Pluses[0] in plugin 1
|
||||
if (RawSignal.Pulses[0]*RawSignal.Multiply > 1000 && RawSignal.Pulses[0]*RawSignal.Multiply < 1400) {
|
||||
command=0;
|
||||
} else
|
||||
if (RawSignal.Pulses[0]*RawSignal.Multiply > 100 && RawSignal.Pulses[0]*RawSignal.Multiply < 400) {
|
||||
command=1;
|
||||
}
|
||||
address=bitstream;
|
||||
}
|
||||
if (command > 1) {
|
||||
//Serial.println("FA500R error3");
|
||||
return false;
|
||||
}
|
||||
if (housecode != 0x01 && housecode != 0x04 && housecode != 0x05 && housecode != 0x00) { // invalid button code?
|
||||
//Serial.println("FA500R error4");
|
||||
return false;
|
||||
}
|
||||
//==================================================================================
|
||||
// if (housecode == 1) housecode = 0x41; // A 0001 0001010 0/1 08 A 1
|
||||
// if (housecode == 4) housecode = 0x42; // B 0100 0001010 0/1 20 B 4
|
||||
// if (housecode == 5) housecode = 0x43; // C 0101 0001010 0/1 28 C 5
|
||||
// if (housecode == 0) housecode = 0x44; // D 0000 0001010 0/1 00 D 0
|
||||
// ----------------------------------
|
||||
// Output
|
||||
// ----------------------------------
|
||||
sprintf(pbuffer, "20;%02X;", PKSequenceNumber++); // Node and packet number
|
||||
Serial.print( pbuffer );
|
||||
// ----------------------------------
|
||||
Serial.print(F("FA500;")); // Label
|
||||
if (type == 0) {
|
||||
sprintf(pbuffer, "ID=%02x%02x;", unitcode, housecode); // ID
|
||||
} else {
|
||||
sprintf(pbuffer, "ID=%08lx;",(address) ); // ID
|
||||
}
|
||||
Serial.print( pbuffer );
|
||||
if (type == 0) {
|
||||
sprintf(pbuffer, "SWITCH=%02x%02x;", unitcode, housecode); // ID
|
||||
} else {
|
||||
sprintf(pbuffer, "SWITCH=%02x;", housecode); // ID
|
||||
}
|
||||
Serial.print( pbuffer );
|
||||
Serial.print(F("CMD="));
|
||||
if ( command == 1) {
|
||||
Serial.print(F("ON;"));
|
||||
} else
|
||||
if ( command == 0) {
|
||||
Serial.print(F("OFF;"));
|
||||
} else {
|
||||
Serial.print(F("UNKOWN;"));
|
||||
}
|
||||
Serial.println();
|
||||
// ----------------------------------
|
||||
RawSignal.Repeats=true; // suppress repeats of the same RF packet
|
||||
return true;
|
||||
}
|
||||
#endif //PLUGIN_012
|
||||
|
||||
#ifdef PLUGIN_TX_012
|
||||
void Flamingo_Send(int funitc, int fcmd);
|
||||
|
||||
boolean PluginTX_012(byte function, char *string) {
|
||||
boolean success=false;
|
||||
//10;FA500;001b523;D3;ON;
|
||||
//012345678901234567890123
|
||||
if (strncasecmp(InputBuffer_Serial+3,"FA500;",6) == 0) { // FA500 Command
|
||||
if (InputBuffer_Serial[16] != ';') return false;
|
||||
unsigned long bitstream=0L;
|
||||
byte Home=0;
|
||||
byte c;
|
||||
|
||||
InputBuffer_Serial[7]=0x30;
|
||||
InputBuffer_Serial[8]=0x78;
|
||||
bitstream=str2int(InputBuffer_Serial+7); // get address
|
||||
|
||||
c=tolower(InputBuffer_Serial[17]); // 1..5
|
||||
if(c>='1' && c<='5'){Home=Home+c-'0';}
|
||||
|
||||
c=0;
|
||||
c |= str2cmd(InputBuffer_Serial+20)==VALUE_OFF; // ON/OFF command
|
||||
Flamingo_Send(bitstream, c);
|
||||
success=true;
|
||||
}
|
||||
return success;
|
||||
}
|
||||
|
||||
void Flamingo_Send(int fbutton, int fcmd) {
|
||||
int fpulse = 350; // Pulse witdh in microseconds
|
||||
int fretrans = 9; // Number of code retransmissions
|
||||
uint32_t fdatabit;
|
||||
uint32_t fdatamask = 0x80000000;
|
||||
uint32_t fsendbuff;
|
||||
uint32_t fsendbuff1;
|
||||
uint32_t fsendbuff2;
|
||||
uint32_t fsendbuff3;
|
||||
uint32_t fsendbuff4;
|
||||
|
||||
if (fcmd == 0) { // OFF
|
||||
fsendbuff1=0x24D319A0; // A Off
|
||||
fsendbuff2=0x246008E0;
|
||||
fsendbuff3=0x26BB9860;
|
||||
fsendbuff4=0x26D4BFA0;
|
||||
//fsendbuff1=0xD86E6650;
|
||||
//fsendbuff2=0xDABDF710;
|
||||
//fsendbuff3=0xDA42A790;
|
||||
//fsendbuff4=0xDA614050;
|
||||
} else { // ON
|
||||
fsendbuff1=0x2561B560; // A On
|
||||
fsendbuff2=0x24A3F5E0;
|
||||
fsendbuff3=0x27B27B60;
|
||||
fsendbuff4=0x24543A20;
|
||||
//fsendbuff1=0xD97A4A10;
|
||||
//fsendbuff2=0xDA9A8490;
|
||||
//fsendbuff3=0xDB58C5D0;
|
||||
//fsendbuff4=0xDBF40A90;
|
||||
}
|
||||
digitalWrite(PIN_RF_RX_VCC,LOW); // Spanning naar de RF ontvanger uit om interferentie met de zender te voorkomen.
|
||||
digitalWrite(PIN_RF_TX_VCC,HIGH); // zet de 433Mhz zender aan
|
||||
delayMicroseconds(TRANSMITTER_STABLE_DELAY); // short delay to let the transmitter become stable (Note: Aurel RTX MID needs 500µS/0,5ms)
|
||||
|
||||
for (int nRepeat = 0; nRepeat < fretrans; nRepeat++) {
|
||||
|
||||
if (nRepeat %4 ==0 ) fsendbuff=fsendbuff1;
|
||||
if (nRepeat %4 ==1 ) fsendbuff=fsendbuff2;
|
||||
if (nRepeat %4 ==2 ) fsendbuff=fsendbuff3;
|
||||
if (nRepeat %4 ==3 ) fsendbuff=fsendbuff4;
|
||||
|
||||
Serial.println(fsendbuff,HEX);
|
||||
|
||||
// send SYNC 1P High, 15P low
|
||||
digitalWrite(PIN_RF_TX_DATA, HIGH);
|
||||
delayMicroseconds(fpulse * 1);
|
||||
digitalWrite(PIN_RF_TX_DATA, LOW);
|
||||
delayMicroseconds(fpulse * 15);
|
||||
// end send SYNC
|
||||
|
||||
// Send command
|
||||
for (int i = 0; i < 28; i++) { // Flamingo command is only 28 bits
|
||||
// read data bit
|
||||
fdatabit = fsendbuff & fdatamask; // Get most left bit
|
||||
fsendbuff = (fsendbuff << 1); // Shift left
|
||||
|
||||
if (fdatabit != fdatamask) { // Write 0
|
||||
digitalWrite(PIN_RF_TX_DATA, HIGH);
|
||||
delayMicroseconds(fpulse * 1);
|
||||
digitalWrite(PIN_RF_TX_DATA, LOW);
|
||||
delayMicroseconds(fpulse * 3);
|
||||
} else { // Write 1
|
||||
digitalWrite(PIN_RF_TX_DATA, HIGH);
|
||||
delayMicroseconds(fpulse * 3);
|
||||
digitalWrite(PIN_RF_TX_DATA, LOW);
|
||||
delayMicroseconds(fpulse * 1);
|
||||
}
|
||||
}
|
||||
//digitalWrite(PIN_RF_TX_DATA, LOW);
|
||||
//delayMicroseconds(fpulse * 15);
|
||||
}
|
||||
delayMicroseconds(TRANSMITTER_STABLE_DELAY); // short delay to let the transmitter become stable (Note: Aurel RTX MID needs 500µS/0,5ms)
|
||||
digitalWrite(PIN_RF_TX_VCC,LOW); // zet de 433Mhz zender weer uit
|
||||
digitalWrite(PIN_RF_RX_VCC,HIGH); // Spanning naar de RF ontvanger weer aan.
|
||||
RFLinkHW();
|
||||
}
|
||||
#endif //PLUGIN_TX_012
|
|
@ -0,0 +1,276 @@
|
|||
//#######################################################################################################
|
||||
//## This Plugin is only for use with the RFLink software package ##
|
||||
//## Plugin-13: Powerfix RCB-i 3600 ##
|
||||
//#######################################################################################################
|
||||
/*********************************************************************************************\
|
||||
* This plugin takes care of sending and receiving the Powerfix RCB-i 3600 protocol
|
||||
* Works with: Powerfix RCB-i 3600 - 4 power outlets and a remote, Quigg GT7000
|
||||
*
|
||||
* Author : StuntTeam
|
||||
* 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!
|
||||
***********************************************************************************************
|
||||
* Technical information:
|
||||
* Partially based on http://wiki.pilight.org/doku.php/quigg_switch_gt_7000_v7_0
|
||||
*
|
||||
* The Powerfix/Chacon RF packets are 42 pulses long resulting in 20 bits data packets
|
||||
*
|
||||
* 0000 1000 0000 000 1 0 0 0 1
|
||||
* AAAA AAAA AAAA BBC D E F G H
|
||||
*
|
||||
* A = 12 bits address (Chacon:0000 0000 0000 Powerfix:0000 1000 0000)
|
||||
* B = 2 bits Unit code (bits reversed)
|
||||
* C = Group Command (to all devices)
|
||||
* D = State (ON/OFF/DIM UP/DIM DOWN)
|
||||
* E = Dim command (1=dim/bright command)
|
||||
* F = always 0
|
||||
* G = Parity bit calculated over command bits (BCDEFH)
|
||||
* H = unknown, copy of D (state)
|
||||
*
|
||||
* -------------------------------------------
|
||||
* Powerfix:
|
||||
* 0000 1000 0000 000 1 0 0 0 1 1 on
|
||||
* 0000 1000 0000 000 0 0 0 0 0 1 off
|
||||
* 0000 1000 0000 100 1 0 0 1 1 2 on
|
||||
* 0000 1000 0000 100 0 0 0 1 0 2 off
|
||||
* 0000 1000 0000 010 1 0 0 0 0 3 on
|
||||
* 0000 1000 0000 010 0 0 0 0 1 3 off
|
||||
* 0000 1000 0000 110 1 0 0 1 0 4 on
|
||||
* 0000 1000 0000 110 0 0 0 1 1 4 off
|
||||
* 0000 1000 0000 111 0 0 0 0 1 all off
|
||||
* 0000 1000 0000 111 1 0 0 0 0 all on
|
||||
* 0000 1000 0000 111 1 1 0 1 0 dim
|
||||
* 0000 1000 0000 111 0 1 0 1 1 bright
|
||||
* -------------------------------------------
|
||||
* Chacon:
|
||||
* 0000 0000 0000 000 1 0 0 0 1 1 ON
|
||||
* 0000 0000 0000 000 0 0 0 0 0 1 OFF
|
||||
* 0000 0000 0000 100 1 0 0 1 1 2 ON
|
||||
* 0000 0000 0000 100 0 0 0 1 0 2 OFF
|
||||
* 0000 0000 0000 010 1 0 0 0 0 3 ON
|
||||
* 0000 0000 0000 010 0 0 0 0 1 3 OFF
|
||||
* 0000 0000 0000 110 1 0 0 1 0 4 ON
|
||||
* 0000 0000 0000 110 0 0 0 1 1 4 OFF
|
||||
* 0000 0000 0000 111 1 0 0 0 0 All ON
|
||||
* 0000 0000 0000 111 0 0 0 0 1 All OFF
|
||||
* 0000 0000 0000 111 1 1 0 1 0 All DIM
|
||||
* 0000 0000 0000 111 0 1 0 1 1 All Bright
|
||||
* -------------------------------------------
|
||||
* Sample Powerfix:
|
||||
* 20;10;DEBUG;Pulses=42;Pulses(uSec)=630,570,1230,540,1230,540,1230,540,1230,570,1230,540,1230,540,1230,540,1230,570,1230,540,1230,540,1230,540,1230,570,1200,540,1200,570,1170,1230,540,570,1200,540,1200,540,1170,1230,540,6990;
|
||||
*
|
||||
* BUTTON: DIM
|
||||
* 20;05;DEBUG;Pulses=42;Pulses(uSec)=600,600,1250,625,1250,625,1225,625,1250,1275,575,600,1250,625,1225,625,1250,625,1225,625,1225,625,1225,625,1225,1300,575,1300,575,1300,575,1300,600,1300,550,625,1225,1300,550,625,1175;
|
||||
* 00101010110010101010101011010101010011001
|
||||
* BUTTON: BRIGHT
|
||||
* 20;12;DEBUG;Pulses=42;Pulses(uSec)=600,600,1250,600,1250,600,1250,600,1250,1275,575,625,1225,625,1225,625,1250,625,1225,625,1225,625,1225,625,1250,1300,550,1300,575,1300,550,625,1250,1300,550,625,1225,1300,575,1300,525;
|
||||
* 00101010110010101010101011010100110011010
|
||||
* BUTTON: ALL OFF
|
||||
* 20;18;DEBUG;Pulses=42;Pulses(uSec)=600,600,1250,625,1225,625,1225,625,1250,1275,575,625,1225,625,1225,625,1250,625,1225,625,1225,625,1225,625,1225,1300,575,1300,550,1300,550,625,1250,650,1200,625,1225,650,1225,1300,500;
|
||||
* 00101010110010101010101011010100101010110
|
||||
* BUTTON: ALL ON
|
||||
* 20;15;DEBUG;Pulses=42;Pulses(uSec)=600,600,1250,600,1250,625,1225,625,1225,1275,575,625,1225,625,1225,625,1250,625,1225,650,1200,625,1225,625,1225,1300,550,1300,575,1300,550,1300,575,650,1225,625,1225,625,1225,625,1175;
|
||||
* 00101010110010101010101011010101001010101
|
||||
* BUTTON: 1 ON
|
||||
* 20;04;DEBUG;Pulses=42;Pulses(uSec)=600,600,1250,625,1225,625,1225,625,1225,1300,575,625,1225,625,1225,625,1250,625,1225,625,1225,625,1225,625,1225,625,1225,625,1225,625,1225,1300,575,625,1225,625,1225,625,1225,1300,500;
|
||||
* 0101010110010101010101010101011001010110
|
||||
* BUTTON: 1 OFF
|
||||
* 20;07;DEBUG;Pulses=42;Pulses(uSec)=600, 600,1250,600,1250,625,1250,625,1225,1275,575,625,1225,600,1250,625,1275,625,1225,625,1225,625,1225,625,1225,625,1225,625,1225,625,1225,625,1250,625,1225,625,1225,625,1225,625,1175;
|
||||
* 0101010110010101010101010101010101010101
|
||||
* BUTTON: 2 ON
|
||||
* 20;0A;DEBUG;Pulses=42;Pulses(uSec)=575,600,1250,625,1225,625,1225,625,1225,1300,550,625,1225,625,1225,625,1275,625,1225,625,1225,625,1225,625,1225,1300,550,625,1225,625,1225,1300,575,625,1225,625,1225,1300,575,1300,500;
|
||||
* 0101010110010101010101011001011001011010
|
||||
* BUTTON: 2 OFF
|
||||
* 20;0D;DEBUG;Pulses=42;Pulses(uSec)=600,600,1250,625,1225,625,1225,625,1250,1300,550,625,1225,625,1225,625,1250,625,1225,625,1225,625,1225,625,1250,1300,575,625,1225,625,
|
||||
1225,625,1250,625,1225,650,1225,1300,550,625,1175;
|
||||
* 0101010110010101010101011001010101011001
|
||||
\*********************************************************************************************/
|
||||
#define POWERFIX_PulseLength 42
|
||||
#define POWEFIX_PULSEMID 900/RAWSIGNAL_SAMPLE_RATE
|
||||
#define POWEFIX_PULSEMIN 450/RAWSIGNAL_SAMPLE_RATE
|
||||
#define POWEFIX_PULSEMAX 1400/RAWSIGNAL_SAMPLE_RATE
|
||||
|
||||
#ifdef PLUGIN_013
|
||||
boolean Plugin_013(byte function, char *string) {
|
||||
if (RawSignal.Number!= POWERFIX_PulseLength) return false;
|
||||
unsigned long bitstream=0L;
|
||||
unsigned int address=0;
|
||||
byte unitcode=0;
|
||||
byte button=0;
|
||||
byte command=0;
|
||||
byte parity=0;
|
||||
byte bitcount=0;
|
||||
// ==========================================================================
|
||||
if (RawSignal.Pulses[1] > POWEFIX_PULSEMID) return false; // start pulse must be short
|
||||
for (byte x=2;x<POWERFIX_PulseLength-1;x+=2) {
|
||||
if (RawSignal.Pulses[x] > POWEFIX_PULSEMID) {
|
||||
if (RawSignal.Pulses[x] > POWEFIX_PULSEMAX) return false; // Long pulse too long
|
||||
if (RawSignal.Pulses[x+1] > POWEFIX_PULSEMID) return false; // pulse sequence check 01/10
|
||||
bitstream = (bitstream << 1) | 0x1;
|
||||
if (bitcount > 11) parity=parity^1;
|
||||
} else {
|
||||
if (RawSignal.Pulses[x] < POWEFIX_PULSEMIN) return false; // Short pulse too short
|
||||
if (RawSignal.Pulses[x+1] < POWEFIX_PULSEMID) return false; // pulse sequence check 01/10
|
||||
bitstream = (bitstream << 1);
|
||||
}
|
||||
bitcount++;
|
||||
}
|
||||
//==================================================================================
|
||||
// Perform Sanity Checks
|
||||
if (parity != 0) return false; // Parity check
|
||||
if (((bitstream)&0x4) == 4) return false; // Tested bit should always be zero
|
||||
//==================================================================================
|
||||
// Prevent repeating signals from showing up
|
||||
//==================================================================================
|
||||
if(SignalHash!=SignalHashPrevious || (RepeatingTimer<millis()+1500) || SignalCRC != bitstream ) {
|
||||
// not seen the RF packet recently
|
||||
SignalCRC=bitstream;
|
||||
} else {
|
||||
// already seen the RF packet recently
|
||||
return true;
|
||||
}
|
||||
//==================================================================================
|
||||
// Sort data
|
||||
address=((bitstream)>>8); // 12 bits address
|
||||
unitcode=((bitstream >> 6)& 0x03);
|
||||
if (unitcode==2) button=1; // bits are simply reversed
|
||||
if (unitcode==1) button=2;
|
||||
if (unitcode==3) button=3;
|
||||
|
||||
parity=((bitstream)&0x3f); // re-use parity variable
|
||||
command=((parity)>>4)&0x01; // On/Off command
|
||||
if (((parity)&0x08) == 0x08) { // dim command
|
||||
command=command+2;
|
||||
} else {
|
||||
if (((parity)&0x20) == 0x20) { // group command
|
||||
command=command+4;
|
||||
}
|
||||
}
|
||||
//==================================================================================
|
||||
// ----------------------------------
|
||||
// Output
|
||||
// ----------------------------------
|
||||
sprintf(pbuffer, "20;%02X;", PKSequenceNumber++); // Node and packet number
|
||||
Serial.print( pbuffer );
|
||||
// ----------------------------------
|
||||
Serial.print(F("Powerfix;")); // Label
|
||||
sprintf(pbuffer, "ID=%04x;", address); // ID
|
||||
Serial.print( pbuffer );
|
||||
sprintf(pbuffer, "SWITCH=%02x;", button); // ID
|
||||
Serial.print( pbuffer );
|
||||
Serial.print(F("CMD="));
|
||||
|
||||
if ( command == 0) {
|
||||
Serial.print(F("OFF;"));
|
||||
} else
|
||||
if ( command == 1) {
|
||||
Serial.print(F("ON;"));
|
||||
} else
|
||||
if ( command == 2) {
|
||||
Serial.print(F("BRIGHT;"));
|
||||
} else
|
||||
if ( command == 3) {
|
||||
Serial.print(F("DIM;"));
|
||||
} else
|
||||
if ( command == 4) {
|
||||
Serial.print(F("ALLOFF;"));
|
||||
} else
|
||||
if ( command == 5) {
|
||||
Serial.print(F("ALLON;"));
|
||||
}
|
||||
Serial.println();
|
||||
// ----------------------------------
|
||||
RawSignal.Repeats=true; // suppress repeats of the same RF packet
|
||||
RawSignal.Number=0;
|
||||
return true;
|
||||
}
|
||||
#endif //PLUGIN_013
|
||||
|
||||
#ifdef PLUGIN_TX_013
|
||||
void Powerfix_Send(unsigned long bitstream);
|
||||
|
||||
boolean PluginTX_013(byte function, char *string) {
|
||||
boolean success=false;
|
||||
//10;POWERFIX;000080;0;ON;
|
||||
//012345678901234567890123
|
||||
if (strncasecmp(InputBuffer_Serial+3,"POWERFIX;",9) == 0) {
|
||||
if (InputBuffer_Serial[18] != ';') return success;
|
||||
|
||||
InputBuffer_Serial[10]=0x30;
|
||||
InputBuffer_Serial[11]=0x78;
|
||||
InputBuffer_Serial[18]=0x00; // Get address from hexadecimal value
|
||||
|
||||
unsigned long bitstream=0L; // Main placeholder
|
||||
byte command=0;
|
||||
byte c;
|
||||
// -------------------------------
|
||||
bitstream=str2int(InputBuffer_Serial+10); // Address, first 12 bits of the 20 bits in total
|
||||
bitstream=(bitstream)<<8; // shift left so that we can add the 8 command bits
|
||||
// -------------------------------
|
||||
byte temp=str2int(InputBuffer_Serial+19);// button/unit number (0..3)
|
||||
if (temp==1) command=0x82;
|
||||
if (temp==2) command=0x40;
|
||||
if (temp==3) command=0xc2;
|
||||
// -------------------------------
|
||||
c=0;
|
||||
c = str2cmd(InputBuffer_Serial+21); // ON/OFF command
|
||||
if (c == VALUE_ON) {
|
||||
command=command | 0x10; // turn "on" bit for on command
|
||||
} else {
|
||||
if (c == VALUE_ALLOFF) { // set "all off" bits
|
||||
command=0xe0;
|
||||
} else
|
||||
if (c == VALUE_ALLON) {
|
||||
command=0xf0; // set "all on" bits
|
||||
}
|
||||
}
|
||||
// not supported yet..
|
||||
// dim: command=0xfa
|
||||
// bright: command=0xea;
|
||||
// -------------------------------
|
||||
bitstream=bitstream+command;
|
||||
// -------------------------------
|
||||
Powerfix_Send(bitstream); // bitstream to send
|
||||
success=true;
|
||||
}
|
||||
return success;
|
||||
}
|
||||
|
||||
#define PLUGIN_013_RFLOW 650
|
||||
#define PLUGIN_013_RFHIGH 1300
|
||||
|
||||
void Powerfix_Send(unsigned long bitstream) {
|
||||
RawSignal.Repeats=7; // Number of RF packet retransmits
|
||||
RawSignal.Delay=20; // Delay between RF packets
|
||||
RawSignal.Number=42; // Length
|
||||
|
||||
uint32_t fdatabit;
|
||||
uint32_t fdatamask = 0x80000;
|
||||
byte parity=1; // to calculate the parity bit
|
||||
// -------------------------------
|
||||
RawSignal.Pulses[1]=PLUGIN_013_RFLOW/RawSignal.Multiply; // start pulse
|
||||
for (byte i=2; i<40; i=i+2) { // address and command bits
|
||||
fdatabit = bitstream & fdatamask; // Get most left bit
|
||||
bitstream = (bitstream << 1); // Shift left
|
||||
|
||||
if (fdatabit != fdatamask) { // Write 0
|
||||
RawSignal.Pulses[i] = PLUGIN_013_RFLOW/RawSignal.Multiply;
|
||||
RawSignal.Pulses[i+1]= PLUGIN_013_RFHIGH/RawSignal.Multiply;
|
||||
} else { // Write 1
|
||||
parity=parity^1;
|
||||
RawSignal.Pulses[i] = PLUGIN_013_RFHIGH/RawSignal.Multiply;
|
||||
RawSignal.Pulses[i+1]= PLUGIN_013_RFLOW/RawSignal.Multiply;
|
||||
}
|
||||
}
|
||||
// parity
|
||||
if (parity == 0) { // Write 0
|
||||
RawSignal.Pulses[40] = PLUGIN_013_RFLOW/RawSignal.Multiply;
|
||||
RawSignal.Pulses[41] = PLUGIN_013_RFHIGH/RawSignal.Multiply;
|
||||
} else { // Write 1
|
||||
RawSignal.Pulses[40] = PLUGIN_013_RFHIGH/RawSignal.Multiply;
|
||||
RawSignal.Pulses[41] = PLUGIN_013_RFLOW/RawSignal.Multiply;
|
||||
}
|
||||
RawSendRF();
|
||||
}
|
||||
#endif // PLUGIN_TX_013
|
|
@ -0,0 +1,147 @@
|
|||
//#######################################################################################################
|
||||
//## This Plugin is only for use with the RFLink software package ##
|
||||
//## Plugin-14: Ikea Koppla ##
|
||||
//#######################################################################################################
|
||||
/*********************************************************************************************\
|
||||
* This plugin takes care of sending and receiving the Ikea Koppla protocol
|
||||
*
|
||||
* Author : StuntTeam
|
||||
* 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!
|
||||
***********************************************************************************************
|
||||
* Technical information:
|
||||
* Packets are variable length as zero bits are 2 pulses and 1 bits are single pulses.
|
||||
* Pulse lengths are ~1600 for a 0 bit and two times ~750 for a 1 bit
|
||||
* Packets contain 28 bits
|
||||
*
|
||||
* AAAA BBBB CCCCCCCCCC DD EEEEEE FF
|
||||
* 1110 0011 0000000001 01 000010 01 on
|
||||
* 1110 0011 0000000001 01 010110 01 off
|
||||
* 1110 1111 1111111111 00 001110 10 Pair
|
||||
*
|
||||
* A = Preamble, Always '1110'
|
||||
* B = System code 0-0x0f
|
||||
* C = Unit code bit selection, order: ch10,1,2,3,4,5,6,7,8,9
|
||||
* D = Checksum on B
|
||||
* E = Level and Fade
|
||||
* F = Checksum on D
|
||||
*
|
||||
* Sample:
|
||||
* 20;07;DEBUG;Pulses=38;Pulses(uSec)=825,775,750,775,750,775,1600,1625,1600,775,750,775,750,1625,1600,1625,1600,1625,1625,1625,1600,1625,750,750,1600,775,750,1625,1600,1625,1600,775,750,1625,1600,775,750;
|
||||
* 20;08;DEBUG;Pulses=40;Pulses(uSec)=925,775,750,775,750,775,1600,1625,1600,775,750,775,750,1625,1600,1625,1600,1625,1625,1625,1600,1625,750,775,1600,775,750,1625,750,750,1625,775,750,775,750,1625,1600,750,750;
|
||||
\*********************************************************************************************/
|
||||
#define KOPPLA_PulseLength_MIN 36
|
||||
#define KOPPLA_PulseLength_MAX 52
|
||||
#define KOPPLA_PULSEMID 1300/RAWSIGNAL_SAMPLE_RATE
|
||||
#define KOPPLA_PULSEMAX 1850/RAWSIGNAL_SAMPLE_RATE
|
||||
#define KOPPLA_PULSEMIN 650/RAWSIGNAL_SAMPLE_RATE
|
||||
|
||||
#ifdef PLUGIN_014
|
||||
boolean Plugin_014(byte function, char *string) {
|
||||
if ((RawSignal.Number < KOPPLA_PulseLength_MIN) || (RawSignal.Number > KOPPLA_PulseLength_MAX) ) return false;
|
||||
unsigned long bitstream=0L;
|
||||
|
||||
byte preamble=0;
|
||||
unsigned int sysunit=0;
|
||||
byte levelfade=0;
|
||||
byte command=0;
|
||||
byte level=0;
|
||||
int i=0;
|
||||
|
||||
byte checksum1=0;
|
||||
byte checksum2=0;
|
||||
byte checksum=0x03;
|
||||
byte tempcrc=0;
|
||||
// ==========================================================================
|
||||
for (byte x=1;x < RawSignal.Number;x++) {
|
||||
if (RawSignal.Pulses[x] > KOPPLA_PULSEMID) { // long pulse, 0 bit
|
||||
if (RawSignal.Pulses[x] > KOPPLA_PULSEMAX) return false; // long pulse is too long
|
||||
bitstream = (bitstream << 1); // 0 bit
|
||||
} else { // Short pulse
|
||||
if (RawSignal.Pulses[x] < KOPPLA_PULSEMIN) return false; // short pulse is too short
|
||||
if (RawSignal.Pulses[x+1] > KOPPLA_PULSEMID) return false; // need 2 short pulses for a 1 bit
|
||||
if (RawSignal.Pulses[x+1] < KOPPLA_PULSEMIN) return false; // second short pulse is too short
|
||||
x++; // skip second short pulse
|
||||
bitstream = (bitstream << 1) | 0x1; // 1 bit
|
||||
}
|
||||
}
|
||||
//==================================================================================
|
||||
// Sort data and perform sanity checks
|
||||
//==================================================================================
|
||||
if (bitstream==0) return false; // No bits detected?
|
||||
if ((((bitstream) >> 24)&0x0f) != 0x0e) return false; // Preamble should always be '1110'
|
||||
sysunit=(((bitstream) >> 10)& 0x03fff); // 4 bits system code and 10 bits unit code
|
||||
checksum1=(((bitstream) >> 8) &0x03); // first checksum
|
||||
levelfade=(((bitstream) >> 2)& 0x3f); // 6 bits level and face code
|
||||
checksum2=((bitstream)&0x03); // second checksum
|
||||
// calculate checksum 1
|
||||
checksum=3;
|
||||
for (i=0;i<7;i++) {
|
||||
tempcrc=((sysunit) >> (i*2)) & 3;
|
||||
checksum=checksum ^ tempcrc;
|
||||
}
|
||||
if (checksum1 != checksum) return false;
|
||||
// calculate checksum 2
|
||||
checksum=3;
|
||||
for (i=0;i<3;i++) {
|
||||
tempcrc=((levelfade) >> (i*2)) & 3;
|
||||
checksum=checksum ^ tempcrc;
|
||||
}
|
||||
if (checksum2 != checksum) return false;
|
||||
// sort command / dim bits
|
||||
if ((levelfade) == 0x2) { // on
|
||||
command=1;
|
||||
} else
|
||||
if ((levelfade) == 0x16) { // off
|
||||
command=0;
|
||||
} else
|
||||
if ((levelfade) == 0x0) { // up
|
||||
command=2;
|
||||
} else
|
||||
if ((levelfade) == 0x4) { // down
|
||||
command=3;
|
||||
} else {
|
||||
command=4;
|
||||
for (i=2;i<6;i++) {
|
||||
level=level<<1;
|
||||
level=level | ((levelfade)>>i)&0x01;
|
||||
}
|
||||
}
|
||||
//==================================================================================
|
||||
// ----------------------------------
|
||||
// Output
|
||||
// ----------------------------------
|
||||
sprintf(pbuffer, "20;%02X;", PKSequenceNumber++); // Node and packet number
|
||||
Serial.print( pbuffer );
|
||||
// ----------------------------------
|
||||
Serial.print(F("Ikea Koppla;")); // Label
|
||||
sprintf(pbuffer, "ID=%04x;", sysunit); // ID
|
||||
Serial.print( pbuffer );
|
||||
sprintf(pbuffer, "SWITCH=%02x;", levelfade); // ID
|
||||
Serial.print( pbuffer );
|
||||
Serial.print(F("CMD="));
|
||||
|
||||
if ( command == 0) {
|
||||
Serial.print(F("OFF;"));
|
||||
} else
|
||||
if ( command == 1) {
|
||||
Serial.print(F("ON;"));
|
||||
} else
|
||||
if ( command == 2) {
|
||||
Serial.print(F("BRIGHT;"));
|
||||
} else
|
||||
if ( command == 3) {
|
||||
Serial.print(F("DIM;"));
|
||||
} else {
|
||||
sprintf(pbuffer, "SET_LEVEL=%d;", level );
|
||||
Serial.print( pbuffer );
|
||||
}
|
||||
Serial.println();
|
||||
// ----------------------------------
|
||||
RawSignal.Repeats=true; // suppress repeats of the same RF packet
|
||||
RawSignal.Number=0;
|
||||
return true;
|
||||
}
|
||||
#endif //PLUGIN_014
|
||||
|
|
@ -0,0 +1,270 @@
|
|||
//#######################################################################################################
|
||||
//## This Plugin is only for use with the RFLink software package ##
|
||||
//## Plugin-15: HomeEasy EU ##
|
||||
//#######################################################################################################
|
||||
/*********************************************************************************************\
|
||||
* Dit protocol zorgt voor ontvangst en verzending HomeEasy EU zenders
|
||||
* die werken volgens de automatische codering (Ontvangers met leer-knop)
|
||||
*
|
||||
* LET OP: GEEN SUPPORT VOOR DIRECTE DIMWAARDES!!!
|
||||
*
|
||||
* Author : StuntTeam
|
||||
* 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:
|
||||
* Analyses Home Easy Messages and convert these into an eventcode
|
||||
* Only new EU devices with automatic code system are supported
|
||||
* Only On / Off status is decoded, no DIM values
|
||||
* Only tested with Home Easy HE300WEU transmitter, doorsensor and PIR sensor
|
||||
* Home Easy message structure, by analyzing bitpatterns so far ...
|
||||
* AAAAAAAAAAA BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB CCCC DD EE FFFFFF G
|
||||
* 11000111100 10111100011101110010001111100011 1100 10 11 000111 1 HE301EU ON
|
||||
* 11000111100 10111100011101110010001111100011 1100 01 11 000111 1 HE301EU OFF
|
||||
* 11000111100 1001 01 11 001011 HE842/844 ON
|
||||
* 11000111100 01111010011100110010001011000111 1000 11 11 001011 0000000 HE842/844 OFF
|
||||
* 1000 10 11 000111 HE844 ALLON;
|
||||
* 1000 01 11 000111 HE844 ALLOFF;
|
||||
* 11000111100 01111000111101100110010011000111 1000 11 11 000111 0000000
|
||||
*
|
||||
* A = Startbits/Preamble,
|
||||
* B = Address, 32 bits
|
||||
* C = Unknown, Possibly: Device type
|
||||
* D = Command, 1 bit only?
|
||||
* E = Group indicator
|
||||
* F = Channel 0-15
|
||||
* G = Stopbit
|
||||
*
|
||||
* SAMPLE:
|
||||
* Pulses=116;Pulses(uSec)=200,1175,125,1175,125,200,150,200,125,200,150,1175,150,1175,150,1175,150,1175,125,200,150,200,150,200,125,1175,150,1175,150,1175,125,1175,150,200,125,200,150,1175,125,1175,150,200,125,1175,125,1175,150,200,150,200,150,1175,150,200,150,1175,150,200,150,1175,150,200,150,200,125,1175,150,200,125,1175,150,1175,125,1175,150,200,125,200,125,200,150,200,125,1175,150,1175,150,1175,150,200,150,200,125,200,150,1175,150,1175,150,1175,150,1175,125,200,150,200,125,1175,125,200,125,1175,150,1150,125;
|
||||
* HE preamble: 11000111100 (63C) Address: 1111001101100101010010111000011 (79B2A5C3) Stopbits: 0 (0) Commands: 10001111001011 Command: 0 Channel: 1011 Group: 1
|
||||
* 20;04;HomeEasy;ID=7900b200;SWITCH=0b;CMD=ALLOFF;
|
||||
*
|
||||
* Preamble 200,1175,125,1175,125,200,150,200,125,200,150,1175,150,1175,150,1175,150,1175,125,200,150,200,
|
||||
* Address 150,200,125,1175,150,1175,150,1175,125,1175,150,200,125,200,150,1175,125,1175,150,200,125,1175,125,1175,150,200,150,200,150,1175,150,200,150,1175,150,200,150,1175,150,200,150,200,125,1175,150,200,125,1175,150,1175,125,1175,150,200,125,200,125,200,150,200,125,1175,150,1175,
|
||||
* Command 150,1175,150,200,150,200,125,200,150,1175,150,1175,150,1175,150,1175,125,200,150,200,125,1175,125,200,125,1175,150,1150, - 125;
|
||||
\*********************************************************************************************/
|
||||
#define HomeEasy_PulseLength 116
|
||||
#define HomeEasy_PULSEMID 500/RAWSIGNAL_SAMPLE_RATE
|
||||
|
||||
#ifdef PLUGIN_015
|
||||
boolean Plugin_015(byte function, char *string) {
|
||||
if (RawSignal.Number != HomeEasy_PulseLength) return false;
|
||||
unsigned long preamble = 0L;
|
||||
unsigned long address = 0L;
|
||||
unsigned long bitstream = 0L;
|
||||
byte rfbit =0;
|
||||
byte command = 0;
|
||||
byte group = 0;
|
||||
byte channel = 0;
|
||||
byte type = 0;
|
||||
byte temp = 0;
|
||||
RawSignal.Pulses[0]=0; // undo any Home Easy to Kaku blocking that might be active
|
||||
//==================================================================================
|
||||
// convert pulses into bit sections (preamble, address, bitstream)
|
||||
for(byte x=1;x<=HomeEasy_PulseLength;x=x+2) {
|
||||
if ((RawSignal.Pulses[x] < HomeEasy_PULSEMID) && (RawSignal.Pulses[x+1] > HomeEasy_PULSEMID))
|
||||
rfbit = 1;
|
||||
else
|
||||
rfbit = 0;
|
||||
|
||||
if ( x<=22) preamble = (preamble << 1) | rfbit; // 11 bits preamble
|
||||
if ((x>=23) && (x<=86)) address = (address << 1) | rfbit; // 32 bits address
|
||||
if ((x>=87) && (x<=114)) bitstream = (bitstream << 1) | rfbit; // 15 remaining bits
|
||||
}
|
||||
//==================================================================================
|
||||
// To prevent false positives make sure the preamble is correct, it should always be 0x63c
|
||||
// We compare only 10 bits to compensate for the first bit being seen incorrectly by some receiver modules
|
||||
if ((preamble & 0x3ff) != 0x23c) return false; // comparing 10 bits is enough to make sure the packet is valid
|
||||
//==================================================================================
|
||||
// Prevent repeating signals from showing up
|
||||
//==================================================================================
|
||||
if(SignalHash!=SignalHashPrevious || (RepeatingTimer<millis()+1500) || SignalCRC != bitstream ) {
|
||||
// not seen the RF packet recently
|
||||
SignalCRC=bitstream;
|
||||
} else {
|
||||
// already seen the RF packet recently
|
||||
return true;
|
||||
}
|
||||
//==================================================================================
|
||||
type = ((bitstream >> 12) & 0x3); // 11b for HE301
|
||||
channel = (bitstream) & 0x3f;
|
||||
if (type==3) { // HE301
|
||||
command = ((bitstream >> 8) & 0x1); // 0=on 1=off (both group and single device)
|
||||
group = ((bitstream >> 7) & 0x1); // 1=group
|
||||
} else { // HE800 21c7 = off 22c7=on
|
||||
temp = ((bitstream >> 8) & 0x7); // 1=group
|
||||
if (temp < 3) group=1;
|
||||
command = ((bitstream >> 9) & 0x1); // 0=off 1=on
|
||||
if (group==1) command=(~command)&1; // reverse bit for group: 1=group off 0=group on
|
||||
}
|
||||
// ----------------------------------
|
||||
// Output
|
||||
// ----------------------------------
|
||||
sprintf(pbuffer, "20;%02X;", PKSequenceNumber++); // Node and packet number
|
||||
Serial.print( pbuffer );
|
||||
// ----------------------------------
|
||||
Serial.print("HomeEasy;"); // Label
|
||||
sprintf(pbuffer, "ID=%08lx;",(address) ); // ID
|
||||
Serial.print( pbuffer );
|
||||
sprintf(pbuffer, "SWITCH=%02x;", channel);
|
||||
Serial.print( pbuffer );
|
||||
strcpy(pbuffer,"CMD=");
|
||||
if ( group == 1) {
|
||||
strcat(pbuffer,"ALL");
|
||||
}
|
||||
if ( command == 1) {
|
||||
strcat(pbuffer,"OFF;");
|
||||
} else {
|
||||
strcat(pbuffer,"ON;");
|
||||
}
|
||||
Serial.print( pbuffer );
|
||||
Serial.println();
|
||||
// ----------------------------------
|
||||
RawSignal.Repeats = true;
|
||||
RawSignal.Number=0;
|
||||
return true;
|
||||
}
|
||||
#endif // PLUGIN_015
|
||||
|
||||
#ifdef PLUGIN_TX_015
|
||||
void HomeEasyEU_Send(unsigned long address, unsigned long command);
|
||||
|
||||
boolean PluginTX_015(byte function, char *string) {
|
||||
boolean success=false;
|
||||
//10;HomeEasy;7900b200;b;ON;
|
||||
//10;HomeEasy;d900ba00;23;OFF;
|
||||
//10;HomeEasy;79b2a5c3;b;ON;
|
||||
//10;HomeEasy;7a7322c7;b;ON;
|
||||
//01234567890123456789012345
|
||||
if (strncasecmp(InputBuffer_Serial+3,"HOMEEASY;",9) == 0) { // KAKU Command eg.
|
||||
if (InputBuffer_Serial[20] != ';') return false;
|
||||
unsigned long bitstream = 0L;
|
||||
unsigned long commandcode = 0L;
|
||||
byte cmd=0;
|
||||
byte group=0;
|
||||
// ------------------------------
|
||||
InputBuffer_Serial[10]=0x30;
|
||||
InputBuffer_Serial[11]=0x78;
|
||||
InputBuffer_Serial[20]=0x00;
|
||||
bitstream=str2int(InputBuffer_Serial+10); // Get Address from hexadecimal value
|
||||
// ------------------------------
|
||||
InputBuffer_Serial[19]=0x30;
|
||||
InputBuffer_Serial[20]=0x78; // Get home from hexadecimal value
|
||||
commandcode=str2int(InputBuffer_Serial+19); // Get Button number
|
||||
// ------------------------------
|
||||
if (InputBuffer_Serial[23] == ';') { // Get command
|
||||
cmd=str2cmd(InputBuffer_Serial+24);
|
||||
} else {
|
||||
cmd=str2cmd(InputBuffer_Serial+23);
|
||||
}
|
||||
if (cmd == VALUE_OFF) cmd = 0; // off
|
||||
if (cmd == VALUE_ON) cmd = 1; // on
|
||||
if (cmd == VALUE_ALLON) {cmd = 1; group=1;} // allon
|
||||
if (cmd == VALUE_ALLOFF){cmd = 0; group=1;} // alloff
|
||||
// ------------------------------
|
||||
commandcode=commandcode & 0x3f; // get button number
|
||||
if (group == 1) { // HE8xx: 21xx/22xx HE3xx: 31xx/32xx (off/on) (HE3xx code works for HE8xx)
|
||||
commandcode=commandcode | 0x30C0; // group
|
||||
if (cmd == 1) {
|
||||
commandcode=(commandcode & 0xfdff) | 0x200; // group on > 32cx
|
||||
} else {
|
||||
commandcode=commandcode | 0x100; // group off > 31cx
|
||||
}
|
||||
} else { // HE8xx: 23cx/25cx HE3xx: 2D4x/2E4x (off/on) (HE3 code works for HE8xx)
|
||||
commandcode=commandcode | 0x2040; // non-group
|
||||
if (cmd == 1) {
|
||||
commandcode=(commandcode & 0xfdff) | 0xe00; // On > 2ECx
|
||||
} else {
|
||||
commandcode=commandcode | 0xd00; // Off > 2DCx
|
||||
}
|
||||
}
|
||||
//-----------------------------------------------
|
||||
HomeEasyEU_Send(bitstream, commandcode);
|
||||
success=true;
|
||||
}
|
||||
return success;
|
||||
}
|
||||
|
||||
void HomeEasyEU_Send(unsigned long address, unsigned long command) {
|
||||
int fpulse = 275; // Pulse witdh in microseconds
|
||||
int fretrans = 5; // Number of code retransmissions
|
||||
uint32_t fdatabit;
|
||||
uint32_t fdatamask = 0x80000000;
|
||||
uint32_t fsendbuff;
|
||||
|
||||
digitalWrite(PIN_RF_RX_VCC,LOW); // Spanning naar de RF ontvanger uit om interferentie met de zender te voorkomen.
|
||||
digitalWrite(PIN_RF_TX_VCC,HIGH); // zet de 433Mhz zender aan
|
||||
delayMicroseconds(TRANSMITTER_STABLE_DELAY); // short delay to let the transmitter become stable (Note: Aurel RTX MID needs 500µS/0,5ms)
|
||||
for (int nRepeat = 0; nRepeat <= fretrans; nRepeat++) {
|
||||
// -------------- Send Home Easy preamble (0x63c) - 11 bits
|
||||
fsendbuff=0x63c;
|
||||
fdatamask=0x400;
|
||||
for (int i = 0; i < 11; i++) { // Preamble
|
||||
// read data bit
|
||||
fdatabit = fsendbuff & fdatamask; // Get most left bit
|
||||
fsendbuff = (fsendbuff << 1); // Shift left
|
||||
if (fdatabit != fdatamask) { // Write 0
|
||||
digitalWrite(PIN_RF_TX_DATA, HIGH);
|
||||
delayMicroseconds(fpulse * 1);
|
||||
digitalWrite(PIN_RF_TX_DATA, LOW);
|
||||
delayMicroseconds(fpulse * 1);
|
||||
} else { // Write 1
|
||||
digitalWrite(PIN_RF_TX_DATA, HIGH);
|
||||
delayMicroseconds(fpulse * 1);
|
||||
digitalWrite(PIN_RF_TX_DATA, LOW);
|
||||
delayMicroseconds(fpulse * 5);
|
||||
}
|
||||
}
|
||||
// -------------- Send Home Easy device Address
|
||||
fsendbuff=address;
|
||||
fdatamask=0x80000000;
|
||||
// Send Address - 32 bits
|
||||
for (int i = 0; i < 32;i++){ //28;i++){
|
||||
// read data bit
|
||||
fdatabit = fsendbuff & fdatamask; // Get most left bit
|
||||
fsendbuff = (fsendbuff << 1); // Shift left
|
||||
if (fdatabit != fdatamask) { // Write 0
|
||||
digitalWrite(PIN_RF_TX_DATA, HIGH);
|
||||
delayMicroseconds(fpulse * 1);
|
||||
digitalWrite(PIN_RF_TX_DATA, LOW);
|
||||
delayMicroseconds(fpulse * 1);
|
||||
} else { // Write 1
|
||||
digitalWrite(PIN_RF_TX_DATA, HIGH);
|
||||
delayMicroseconds(fpulse * 1);
|
||||
digitalWrite(PIN_RF_TX_DATA, LOW);
|
||||
delayMicroseconds(fpulse * 5);
|
||||
}
|
||||
}
|
||||
// -------------- Send Home Easy command bits - 14 bits
|
||||
fsendbuff=command; // 0xFF;
|
||||
fdatamask=0x2000;
|
||||
for (int i = 0; i < 14; i++) {
|
||||
// read data bit
|
||||
fdatabit = fsendbuff & fdatamask; // Get most left bit
|
||||
fsendbuff = (fsendbuff << 1); // Shift left
|
||||
if (fdatabit != fdatamask) { // Write 0
|
||||
digitalWrite(PIN_RF_TX_DATA, HIGH);
|
||||
delayMicroseconds(fpulse * 1);
|
||||
digitalWrite(PIN_RF_TX_DATA, LOW);
|
||||
delayMicroseconds(fpulse * 1);
|
||||
} else { // Write 1
|
||||
digitalWrite(PIN_RF_TX_DATA, HIGH);
|
||||
delayMicroseconds(fpulse * 1);
|
||||
digitalWrite(PIN_RF_TX_DATA, LOW);
|
||||
delayMicroseconds(fpulse * 5);
|
||||
}
|
||||
}
|
||||
// -------------- Send stop
|
||||
digitalWrite(PIN_RF_TX_DATA, HIGH);
|
||||
delayMicroseconds(fpulse * 1);
|
||||
digitalWrite(PIN_RF_TX_DATA, LOW); // and lower the signal
|
||||
delayMicroseconds(fpulse * 26);
|
||||
}
|
||||
delayMicroseconds(TRANSMITTER_STABLE_DELAY); // short delay to let the transmitter become stable (Note: Aurel RTX MID needs 500µS/0,5ms)
|
||||
digitalWrite(PIN_RF_TX_VCC,LOW); // zet de 433Mhz zender weer uit
|
||||
digitalWrite(PIN_RF_RX_VCC,HIGH); // Spanning naar de RF ontvanger weer aan.
|
||||
RFLinkHW();
|
||||
}
|
||||
#endif // PLUGIN_TX_015
|
|
@ -0,0 +1,261 @@
|
|||
//#######################################################################################################
|
||||
//## This Plugin is only for use with the RFLink software package ##
|
||||
//## Plugin-30 AlectoV1 ##
|
||||
//#######################################################################################################
|
||||
/*********************************************************************************************\
|
||||
* This plugin takes care of decoding the protocol used for outdoor sensors of the Alecto weather stations
|
||||
* following protocol version 1
|
||||
* This Plugin works at least with: Alecto WS3500, Silvercrest, Otio sht-10, Otio sht-20
|
||||
* Auriol H13726, Ventus WS155, Hama EWS 1500, Meteoscan W155/W160
|
||||
* Alecto WS4500, Ventus W044, Balance RF-WS105
|
||||
*
|
||||
* Author : StuntTeam
|
||||
* 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:
|
||||
* Message Format: (9 nibbles, 36 bits):
|
||||
*
|
||||
* Format for Temperature Humidity
|
||||
* AAAAAAAA BBBB CCCC CCCC CCCC DDDDDDDD EEEE
|
||||
* 00110110 1000 1011 0111 0000 00011100 0110
|
||||
* RC Type Temperature___ Humidity Checksum
|
||||
* A = Rolling Code (includes channel number on low 2 bits of nibble1 (10=ch1 01=ch2 11=ch3) )
|
||||
* B = Message type (xyyx = temp/humidity if yy <> '11') => only accepting yy = 00 for negative temperatures for now
|
||||
* 4 bits: bit 0 = battery state 0=OK, 1= below 2.6 volt
|
||||
* bit 1&2 = 00/01/10 = temp/hum is transmitted, 11=non temp is transmitted
|
||||
* bit 3 = 0=scheduled transmission, 1=requested transmission (button press)
|
||||
* C = Temperature (two's complement)
|
||||
* D = Humidity BCD format
|
||||
* E = Checksum
|
||||
*
|
||||
* Sample:
|
||||
* 20;F4;DEBUG;Pulses=74;Pulses(uSec)=450,1900,350,1900,350,3975,350,3975,350,1900,350,3975,350,3975,350,1900,350,3975,350,1900,350,1900,350,1900,350,3975,350,1900,350,3975,350,3975,350,1900,350,3975,350,3975,350,3975,350,1900,350,1900,350,1900,350,1900,350,1900,350,1900,350,1900,350,3975,350,3975,350,3975,350,1900,350,1900,350,1900,350,3975,350,3975,350,2025,350;
|
||||
* 20;F5;Alecto V1;ID=006c;TEMP=00ed;HUM=38;
|
||||
*
|
||||
* Format for Rain
|
||||
* AAAAAAAA BBBB CCCC DDDD DDDD DDDD DDDD EEEE
|
||||
* 01100001 0110 1100 1010 1011 0010 0000 0010
|
||||
* RC Type Rain Checksum
|
||||
* A = Rolling Code
|
||||
* B = Message type (xyyx = NON temp/humidity data if yy = '11')
|
||||
* C = fixed to 1100
|
||||
* D = Rain (bitvalue * 0.25 mm)
|
||||
* E = Checksum
|
||||
*
|
||||
* Sample:
|
||||
* 20;A8;DEBUG;Pulses=74;Pulses(uSec)=550,1925,425,4100,425,4100,425,1975,425,1975,425,1975,425,1975,425,4100,400,2000,425,4100,425,4100,425,1975,425,4100,425,4100,425,1975,425,1975,425,4100,425,1975,425,4100,400,1975,425,4100,425,1975,425,4100,425,4100,425,1975,450,1975,425,4100,450,1950,450,1950,450,1950,425,1975,450,1950,450,1950,475,1925,500,4025,475,1950,475;
|
||||
* 20;A9;Alecto V1;ID=0086;RAIN=04d5;
|
||||
*
|
||||
* Format for Windspeed
|
||||
* AAAAAAAA BBBB CCCC CCCC CCCC DDDDDDDD EEEE
|
||||
* RC Type Windspd Checksum
|
||||
* A = Rolling Code
|
||||
* B = Message type (xyyx = NON temp/humidity data if yy = '11')
|
||||
* C = Fixed to 1000 0000 0000
|
||||
* D = Windspeed (bitvalue * 0.2 m/s, correction for webapp = 3600/1000 * 0.2 * 100 = 72)
|
||||
* E = Checksum
|
||||
*
|
||||
* Format for Winddirection & Windgust
|
||||
* AAAAAAAA BBBB CCCD DDDD DDDD EEEEEEEE FFFF
|
||||
01110000 0000 1111 1011 0000 00000000 0101
|
||||
* RC Type Winddir Windgust Checksum
|
||||
* A = Rolling Code
|
||||
* B = Message type (xyyx = NON temp/humidity data if yy = '11')
|
||||
* C = Fixed to 111x
|
||||
* D = Wind direction 0-511 in 0.7 degree steps?
|
||||
* E = Windgust (bitvalue * 0.2 m/s, correction for webapp = 3600/1000 * 0.2 * 100 = 72)
|
||||
* F = Checksum
|
||||
*
|
||||
* Sample:
|
||||
* 20;53;DEBUG;Pulses=74;Pulses(uSec)=425,3800,350,1825,350,1825,325,1825,350,1825,325,3800,350,3800,350,1825,325,3800,350,1825,325,1800,350,1825,350,1825,325,1825,325,3800,325,1825,350,1800,350,1825,325,3825,325,3800,325,1825,325,1825,325,1800,325,1825,350,3800,325,1825,325,3800,350,1800,350,1800,350,3800,350,1825,325,1825,325,1825,325,1825,350,1825,325,1925,325;
|
||||
\*********************************************************************************************/
|
||||
#define WS3500_PULSECOUNT 74
|
||||
|
||||
#ifdef PLUGIN_030
|
||||
boolean Plugin_030(byte function, char *string) {
|
||||
if (RawSignal.Number != WS3500_PULSECOUNT) return false;
|
||||
unsigned long bitstream=0L;
|
||||
byte nibble0=0;
|
||||
byte nibble1=0;
|
||||
byte nibble2=0;
|
||||
byte nibble3=0;
|
||||
byte nibble4=0;
|
||||
byte nibble5=0;
|
||||
byte nibble6=0;
|
||||
byte nibble7=0;
|
||||
byte checksum=0;
|
||||
int temperature=0;
|
||||
byte humidity=0;
|
||||
unsigned int rain=0;
|
||||
byte windspeed=0;
|
||||
byte windgust=0;
|
||||
int winddirection=0;
|
||||
byte checksumcalc = 0;
|
||||
byte rc=0;
|
||||
byte battery=0;
|
||||
//==================================================================================
|
||||
for(byte x=2; x<=64; x=x+2) {
|
||||
if (RawSignal.Pulses[x+1]*RawSignal.Multiply > 700) return false; // in between pulses should be short
|
||||
if (RawSignal.Pulses[x]*RawSignal.Multiply > 2560) {
|
||||
bitstream = ((bitstream >> 1) |(0x1L << 31));
|
||||
} else {
|
||||
bitstream = (bitstream >> 1);
|
||||
}
|
||||
}
|
||||
for(byte x=66; x<=72; x=x+2) {
|
||||
if (RawSignal.Pulses[x]*RawSignal.Multiply > 2560) {
|
||||
checksum = ((checksum >> 1) |(0x1L << 3));
|
||||
} else {
|
||||
checksum = (checksum >> 1);
|
||||
}
|
||||
}
|
||||
//==================================================================================
|
||||
if (bitstream == 0) return false; // Perform a sanity check
|
||||
//==================================================================================
|
||||
// Prevent repeating signals from showing up
|
||||
//==================================================================================
|
||||
if( (SignalHash!=SignalHashPrevious) || ((RepeatingTimer+1000<millis()) && (SignalCRC != bitstream)) || (SignalCRC != bitstream) ) {
|
||||
// not seen the RF packet recently
|
||||
SignalCRC=bitstream;
|
||||
} else {
|
||||
// already seen the RF packet recently
|
||||
return true;
|
||||
}
|
||||
//==================================================================================
|
||||
// Sort nibbles
|
||||
nibble7 = (bitstream >> 28) & 0xf;
|
||||
nibble6 = (bitstream >> 24) & 0xf;
|
||||
nibble5 = (bitstream >> 20) & 0xf;
|
||||
nibble4 = (bitstream >> 16) & 0xf;
|
||||
nibble3 = (bitstream >> 12) & 0xf;
|
||||
nibble2 = (bitstream >> 8) & 0xf;
|
||||
nibble1 = (bitstream >> 4) & 0xf;
|
||||
nibble0 = bitstream & 0xf;
|
||||
//==================================================================================
|
||||
// Perform checksum calculations, Alecto checksums are Rollover Checksums by design!
|
||||
if ((nibble2 & 0x6) != 6) { // temperature packet
|
||||
checksumcalc = (0xf - nibble0 - nibble1 - nibble2 - nibble3 - nibble4 - nibble5 - nibble6 - nibble7) & 0xf;
|
||||
} else {
|
||||
if ((nibble3 & 0x7) == 3) { // Rain packet
|
||||
checksumcalc = (0x7 + nibble0 + nibble1 + nibble2 + nibble3 + nibble4 + nibble5 + nibble6 + nibble7) & 0xf;
|
||||
} else { // Wind packet
|
||||
checksumcalc = (0xf - nibble0 - nibble1 - nibble2 - nibble3 - nibble4 - nibble5 - nibble6 - nibble7) & 0xf;
|
||||
}
|
||||
}
|
||||
if (checksum != checksumcalc) return false;
|
||||
//==================================================================================
|
||||
battery=(nibble2)&0x1; // get battery indicator
|
||||
nibble2=(nibble2)&0x06; // prepare nibble to contain only the needed bits
|
||||
nibble3=(nibble3)&0x07; // prepare nibble to contain only the needed bits
|
||||
//==================================================================================
|
||||
rc = bitstream & 0xff;
|
||||
|
||||
if ((nibble2) != 6) { // nibble 2 needs to be set to something other than 'x11x' to be a temperature packet
|
||||
// Temperature packet
|
||||
temperature = (bitstream >> 12) & 0xfff;
|
||||
//fix 12 bit signed number conversion
|
||||
if ((temperature & 0x800) == 0x800) {
|
||||
if ((nibble2 & 0x6) != 0) return false; // reject alecto v4 on alecto v1... (causing high negative temperatures with valid checksums)
|
||||
temperature=4096-temperature; // fix for minus temperatures
|
||||
if (temperature > 0x258) return false; // temperature out of range ( > -60.0 degrees)
|
||||
temperature=temperature | 0x8000; // turn highest bit on for minus values
|
||||
} else {
|
||||
if (temperature > 0x258) return false; // temperature out of range ( > 60.0 degrees)
|
||||
}
|
||||
humidity = (16 * nibble7) + nibble6;
|
||||
if (humidity > 0x99) return false; // Humidity out of range, assume ALL data is bad?
|
||||
//==================================================================================
|
||||
// Output
|
||||
// ----------------------------------
|
||||
sprintf(pbuffer, "20;%02X;", PKSequenceNumber++); // Node and packet number
|
||||
Serial.print( pbuffer );
|
||||
// ----------------------------------
|
||||
Serial.print(F("Alecto V1;")); // Label
|
||||
sprintf(pbuffer, "ID=%02x%02x;", (rc &0x03), (rc &0xfc) ); // ID is split into channel number and rolling code
|
||||
Serial.print( pbuffer );
|
||||
sprintf(pbuffer, "TEMP=%04x;", temperature);
|
||||
Serial.print( pbuffer );
|
||||
if (humidity < 0x99) { // Some AlectoV1 devices actually lack the humidity sensor and always report 99%
|
||||
sprintf(pbuffer, "HUM=%02x;", humidity); // Only report humidity when it is below 99%
|
||||
Serial.print( pbuffer );
|
||||
}
|
||||
if (battery==0) {
|
||||
Serial.print("BAT=OK;");
|
||||
} else {
|
||||
Serial.print("BAT=LOW;");
|
||||
}
|
||||
Serial.println();
|
||||
//==================================================================================
|
||||
RawSignal.Repeats=true; // suppress repeats of the same RF packet
|
||||
RawSignal.Number=0;
|
||||
return true;
|
||||
} else {
|
||||
if ((nibble3) == 3) { // Rain packet
|
||||
rain = ((bitstream >> 16) & 0xffff);
|
||||
//==================================================================================
|
||||
// Output
|
||||
// ----------------------------------
|
||||
sprintf(pbuffer, "20;%02X;", PKSequenceNumber++); // Node and packet number
|
||||
Serial.print( pbuffer );
|
||||
// ----------------------------------
|
||||
Serial.print(F("Alecto V1;")); // Label
|
||||
sprintf(pbuffer, "ID=00%02x;", rc); // ID
|
||||
Serial.print( pbuffer );
|
||||
sprintf(pbuffer, "RAIN=%04x;", rain);
|
||||
Serial.print( pbuffer );
|
||||
Serial.println();
|
||||
//==================================================================================
|
||||
RawSignal.Repeats=true; // suppress repeats of the same RF packet
|
||||
RawSignal.Number=0;
|
||||
return true;
|
||||
}
|
||||
if ((nibble3) == 1) { // windspeed packet
|
||||
windspeed = ((bitstream >> 24) & 0xff);
|
||||
windspeed = windspeed*72;
|
||||
//==================================================================================
|
||||
// Output
|
||||
// ----------------------------------
|
||||
sprintf(pbuffer, "20;%02X;", PKSequenceNumber++); // Node and packet number
|
||||
Serial.print( pbuffer );
|
||||
// ----------------------------------
|
||||
Serial.print(F("Alecto V1;")); // Label
|
||||
sprintf(pbuffer, "ID=00%02x;", rc); // ID
|
||||
Serial.print( pbuffer );
|
||||
sprintf(pbuffer, "WINSP=%04x;", windspeed);
|
||||
Serial.print( pbuffer );
|
||||
Serial.println();
|
||||
//==================================================================================
|
||||
RawSignal.Repeats=true; // suppress repeats of the same RF packet
|
||||
RawSignal.Number=0;
|
||||
return true;
|
||||
}
|
||||
if ((nibble3) == 7) { // winddir packet
|
||||
winddirection = ((bitstream >> 15) & 0x1ff) / 45; // ???
|
||||
winddirection = winddirection & 0x0f;
|
||||
windgust = ((bitstream >> 24) & 0xff);
|
||||
windgust = windgust*72;
|
||||
//==================================================================================
|
||||
// Output
|
||||
// ----------------------------------
|
||||
sprintf(pbuffer, "20;%02X;", PKSequenceNumber++); // Node and packet number
|
||||
Serial.print( pbuffer );
|
||||
// ----------------------------------
|
||||
Serial.print(F("Alecto V1;")); // Label
|
||||
sprintf(pbuffer, "ID=00%02x;", rc); // ID
|
||||
Serial.print( pbuffer );
|
||||
sprintf(pbuffer, "WINDIR=%04d;", winddirection);
|
||||
Serial.print( pbuffer );
|
||||
sprintf(pbuffer, "WINGS=%04x;", windgust);
|
||||
Serial.print( pbuffer );
|
||||
Serial.println();
|
||||
//==================================================================================
|
||||
RawSignal.Repeats=true; // suppress repeats of the same RF packet
|
||||
RawSignal.Number=0;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
#endif // PLUGIN_030
|
|
@ -0,0 +1,181 @@
|
|||
//#######################################################################################################
|
||||
//## This Plugin is only for use with the RFLink software package ##
|
||||
//## Plugin-31 AlectoV3 ##
|
||||
//#######################################################################################################
|
||||
/*********************************************************************************************\
|
||||
* Dit protocol zorgt voor ontvangst van Alecto weerstation buitensensoren
|
||||
* WS1100, WS1200, WSD-19
|
||||
*
|
||||
* Author : StuntTeam
|
||||
* 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!
|
||||
*********************************************************************************************
|
||||
* Changelog: v1.0 initial release
|
||||
*********************************************************************************************
|
||||
* Technische informatie:
|
||||
* Decodes signals from Alecto Weatherstation outdoor unit, type 3 (94/126 pulses, 47/63 bits, 433 MHz).
|
||||
* WS1100 Message Format: (7 bits preamble, 5 Bytes, 40 bits):
|
||||
* AAAAAAA AAAABBBB BBBB__CC CCCCCCCC DDDDDDDD EEEEEEEE
|
||||
* Temperature Humidity Checksum
|
||||
* A = start/unknown, first 8 bits are always 11111111
|
||||
* B = Rolling code
|
||||
* C = Temperature (10 bit value with -400 base)
|
||||
* D = Checksum
|
||||
* E = Humidity
|
||||
*
|
||||
* WS1200 Message Format: (7 bits preamble, 7 Bytes, 56 bits):
|
||||
* AAAAAAA AAAABBBB BBBB__CC CCCCCCCC DDDDDDDD DDDDDDDD EEEEEEEE FFFFFFFF
|
||||
* Temperature Rain LSB Rain MSB ???????? Checksum
|
||||
* A = start/unknown, first 8 bits are always 11111111
|
||||
* B = Rolling code
|
||||
* C = Temperature (10 bit value with -400 base)
|
||||
* D = Rain ( * 0.3 mm)
|
||||
* E = ?
|
||||
* F = Checksum
|
||||
|
||||
AAAAAAA AAAABBBB BBBBCCCC CCCCCCCC DDDDDDDD DDDDDDDD EEEEEEEE FFFFFFFF
|
||||
1111111 00111010 01010010 10000010 00000000 00000000 11111111 10111010 1 24,2 gr 0 mm
|
||||
1111111 00111010 01010010 10000010 00000001 00000000 11111111 11111100 0 24,2 gr 0,3 mm
|
||||
1111111 00111010 01010010 10000010 00000010 00000000 11111111 00110110 0 24,2 gr 0,6 mm
|
||||
1111111 00111010 01010010 10000010 00001000 00000000 11111111 11101000 1 24,2 gr 2,4 mm
|
||||
1111111 00111010 01010010 10000010 00001101 00000000 11111111 10000111 0 24,2 gr 3.9 mm
|
||||
1111111 00111010 01010010 01110001 00001101 00000000 11111111 01000010 0 22,5 gr 3,9 mm
|
||||
1111111 00111010 01010010 01010111 00001101 00000000 11111111 00111011 1 19,9 gr 3,9 mm
|
||||
1111111 00111010 01010010 00111110 00010010 00000000 11111111 00111001 1 17,4 gr 5,4 mm
|
||||
1111111 00111010 01010010 00101000 00010010 00000000 11111111 00001000 0 15,2 gr 5,4 mm
|
||||
|
||||
1111111 00111010 01010001 00101011 10011010 00000001 11111111 10100011 -10,1 gr/123,0 mm
|
||||
WS1200 temp:-101
|
||||
WS1200 rain LSB:154
|
||||
WS1200 rain MSB:1
|
||||
WS1200 rain:1230
|
||||
|
||||
1111111 00111010 01010001 10101101 10011111 00000001 11111111 00110100 2,9 gr/124,5mm
|
||||
WS1200 temp:29
|
||||
WS1200 rain LSB:159
|
||||
WS1200 rain MSB:1
|
||||
WS1200 rain:1245
|
||||
|
||||
|
||||
* 20;AE;DEBUG;Pulses=126;Pulses(uSec)=900,950,825,450,325,450,325,950,325,450,325,450,825,950,825,450,325,950,825,450,350,950,325,450,825,950,825,450,325,450,325,950,825,925,350,450,825,950,825,925,350,450,825,450,350,925,825,450,350,450,325,950,350,450,825,950,325,450,350,450,325,450,825,450,325,450,325,450,325,450,325,950,825,950,325,450,825,950,325,450,825,450,325,950,325,450,325,450,825,925,350,450,350,450,825,950,825,925,350,425,350,450,350,450,350,450,350,450,825,950,825,950,325,450,350,450,825,950,825,950,825,950,325,450,325;
|
||||
* 20;AF;Alecto V3;ID=009a;TEMP=ffe7;RAIN=7a;
|
||||
\*********************************************************************************************/
|
||||
#define WS1100_PULSECOUNT 94
|
||||
#define WS1200_PULSECOUNT 126
|
||||
#define ALECTOV3_PULSEMID 300/RAWSIGNAL_SAMPLE_RATE
|
||||
|
||||
#ifdef PLUGIN_031
|
||||
uint8_t Plugin_031_ProtocolAlectoCRC8( uint8_t *addr, uint8_t len);
|
||||
unsigned int Plugin_031_ProtocolAlectoRainBase=0;
|
||||
|
||||
boolean Plugin_031(byte function, char *string) {
|
||||
if ((RawSignal.Number != WS1100_PULSECOUNT) && (RawSignal.Number != WS1200_PULSECOUNT)) return false;
|
||||
|
||||
unsigned long bitstream1=0L;
|
||||
unsigned long bitstream2=0L;
|
||||
byte rc=0;
|
||||
int temperature=0;
|
||||
byte humidity=0;
|
||||
unsigned int rain=0;
|
||||
byte checksum=0;
|
||||
byte checksumcalc=0;
|
||||
byte data[6];
|
||||
//==================================================================================
|
||||
for (byte x=15; x<=77; x=x+2) { // get first 32 relevant bits
|
||||
if (RawSignal.Pulses[x] < ALECTOV3_PULSEMID) {
|
||||
bitstream1 = (bitstream1 << 1) | 0x1;
|
||||
} else {
|
||||
bitstream1 = (bitstream1 << 1);
|
||||
}
|
||||
}
|
||||
for (byte x=79; x<=141; x=x+2) { // get second 32 relevant bits
|
||||
if (RawSignal.Pulses[x] < ALECTOV3_PULSEMID) {
|
||||
bitstream2 = (bitstream2 << 1) | 0x1;
|
||||
} else {
|
||||
bitstream2 = (bitstream2 << 1);
|
||||
}
|
||||
}
|
||||
//==================================================================================
|
||||
if (bitstream1 == 0) return false; // Sanity check
|
||||
data[0] = (bitstream1 >> 24) & 0xff; // Sort data
|
||||
data[1] = (bitstream1 >> 16) & 0xff;
|
||||
data[2] = (bitstream1 >> 8) & 0xff;
|
||||
data[3] = (bitstream1 >> 0) & 0xff;
|
||||
data[4] = (bitstream2 >> 24) & 0xff;
|
||||
data[5] = (bitstream2 >> 16) & 0xff;
|
||||
// ----------------------------------
|
||||
if (RawSignal.Number == WS1200_PULSECOUNT) { // verify checksum
|
||||
checksum = (bitstream2 >> 8) & 0xff;
|
||||
checksumcalc = Plugin_031_ProtocolAlectoCRC8(data, 6);
|
||||
} else {
|
||||
checksum = (bitstream2 >> 24) & 0xff;
|
||||
checksumcalc = Plugin_031_ProtocolAlectoCRC8(data, 4);
|
||||
}
|
||||
if (checksum != checksumcalc) return false;
|
||||
// ----------------------------------
|
||||
rc = (bitstream1 >> 20) & 0xff;
|
||||
temperature = ((bitstream1 >> 8) & 0x3ff); // 299=12b -400 (0x190) = FF9b
|
||||
//temperature = ((bitstream1 >> 8) & 0x3ff) - 400; // 299=12b -400 (0x190) = FF9b
|
||||
if (temperature < 400) { // negative temperature value
|
||||
temperature = 400 - temperature;
|
||||
temperature=temperature | 0x8000; // turn highest bit on for minus values
|
||||
} else {
|
||||
if (temperature > 0x258) return false; // temperature out of range ( > 60.0 degrees)
|
||||
}
|
||||
//==================================================================================
|
||||
// Output
|
||||
// ----------------------------------
|
||||
sprintf(pbuffer, "20;%02X;", PKSequenceNumber++); // Node and packet number
|
||||
Serial.print( pbuffer );
|
||||
// ----------------------------------
|
||||
Serial.print(F("Alecto V3;")); // Label
|
||||
sprintf(pbuffer, "ID=00%02x;", rc); // ID
|
||||
Serial.print( pbuffer );
|
||||
sprintf(pbuffer, "TEMP=%04x;", temperature);
|
||||
Serial.print( pbuffer );
|
||||
|
||||
if (RawSignal.Number == WS1100_PULSECOUNT) {
|
||||
humidity = bitstream1 & 0xff; // alleen op WS1100?
|
||||
sprintf(pbuffer, "HUM=%02x;", humidity);
|
||||
Serial.print( pbuffer );
|
||||
} else {
|
||||
rain = (((bitstream2 >> 24) & 0xff) * 256) + ((bitstream1 >> 0) & 0xff);
|
||||
// check if rain unit has been reset!
|
||||
if (rain < Plugin_031_ProtocolAlectoRainBase) Plugin_031_ProtocolAlectoRainBase=rain;
|
||||
if (Plugin_031_ProtocolAlectoRainBase > 0) {
|
||||
//UserVar[basevar+1 -1] += ((float)rain - Plugin_031_ProtocolAlectoRainBase) * 0.30;
|
||||
sprintf(pbuffer, "RAIN=%02x;", (rain)&0xff);
|
||||
Serial.print( pbuffer );
|
||||
}
|
||||
Plugin_031_ProtocolAlectoRainBase = rain;
|
||||
}
|
||||
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_031_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_031
|
|
@ -0,0 +1,121 @@
|
|||
//#######################################################################################################
|
||||
//## This Plugin is only for use with the RFLink software package ##
|
||||
//## Plugin-32 AlectoV4 ##
|
||||
//#######################################################################################################
|
||||
/*********************************************************************************************\
|
||||
* This plugin takes care of decoding the protocol used for outdoor sensors of the Alecto weather stations
|
||||
* following protocol version 4
|
||||
* This Plugin works at least with: Banggood SKU174397, Sako CH113, Homemart/Onemall FD030 and Blokker (Dake) 1730796 outdoor sensors
|
||||
* But probably with many others as the OEM sensor is sold under many brand names
|
||||
*
|
||||
* Author : StuntTeam
|
||||
* 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:
|
||||
* Message Format: (9 nibbles, 36 bits):
|
||||
*
|
||||
* Format for Temperature Humidity
|
||||
* AAAAAAAA AAAA BCDD EEEE EEEE EEEE FFFFFFFF
|
||||
* 01011100 0001 1000 1111 0111 1011 00001110
|
||||
01110000 0000 1111 1011 0000 0000 00000101
|
||||
10110101 0000 1x00 01001001
|
||||
|
||||
01000101 1000 0110 1111 0000 1100 00100110
|
||||
01011111 1101 1000 0000 1111 0001 00001110
|
||||
01000101 1000 0010
|
||||
*
|
||||
* A = Rolling Code
|
||||
* B = 1 (fixed value)
|
||||
* C = 0=scheduled transmission, 1=requested transmission (button press)
|
||||
* D = Channel number (00=ch1 01=ch2 10=ch3)
|
||||
* E = Temperature (two's complement)
|
||||
* F = Humidity BCD format
|
||||
*
|
||||
* 20;3F;DEBUG;Pulses=74;Pulses(uSec)=525,1725,425,3600,425,1725,425,3600,425,3625,425,1725,425,3600,425,1725,425,1725,425,1700,425,3600,425,3600,425,3600,425,1725,425,1725,425,1725,425,1725,425,1725,400,1725,425,3600,425,1725,425,1725,425,1725,425,3600,400,1725,425,1725,425,3625,400,1725,425,1725,425,1750,400,3600,425,1725,400,1750,400,3625,425,1725,400,1725,425;
|
||||
* 20;C2;DEBUG;Pulses=76;Pulses(uSec)=325,500,250,1800,375,3650,375,1775,375,3650,375,3650,375,1775,375,3650,375,1800,350,1800,375,3650,375,3650,375,3650,375,3650,375,1775,375,1775,375,1775,375,1775,375,1775,375,1775,375,1775,375,3650,375,3650,375,3650,375,1775,375,3650,375,3650,375,1775,375,1775,375,1775,375,1775,375,1775,375,1775,375,3650,375,3650,375,3650,375,3650,375;
|
||||
* 20;3E;DEBUG;Pulses=78;Pulses(uSec)=525,250,500,375,600,1650,450,3550,475,1675,450,3550,475,3550,450,1675,450,3575,450,1675,450,1700,450,1700,450,3575,425,3600,450,3575,475,1700,425,1725,425,1725,425,1725,400,1725,425,1725,425,3625,425,1725,425,1725,425,1725,425,3600,425,1725,400,1725,425,3600,425,1725,425,1725,400,1725,425,3600,400,1725,425,1725,400,3600,425,1725,425,1725,400;
|
||||
\*********************************************************************************************/
|
||||
#ifdef PLUGIN_032
|
||||
boolean Plugin_032(byte function, char *string) {
|
||||
if (RawSignal.Number < 74 || RawSignal.Number > 78 ) return false;
|
||||
unsigned long bitstream=0L;
|
||||
int temperature=0;
|
||||
int humidity=0;
|
||||
byte rc=0;
|
||||
byte rc2=0;
|
||||
|
||||
//==================================================================================
|
||||
byte start=0;
|
||||
if (RawSignal.Number == 78) start=4;
|
||||
if (RawSignal.Number == 76) start=2;
|
||||
for(int x=2+start; x<=56+start; x=x+2) { // Get first 28 bits
|
||||
if (RawSignal.Pulses[x+1]*RawSignal.Multiply > 550) return false;
|
||||
if (RawSignal.Pulses[x]*RawSignal.Multiply > 3000) {
|
||||
bitstream = (bitstream << 1) | 0x01;
|
||||
} else {
|
||||
if (RawSignal.Pulses[x]*RawSignal.Multiply > 1500) {
|
||||
if (RawSignal.Pulses[x]*RawSignal.Multiply > 2100) return false;
|
||||
bitstream = (bitstream << 1);
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
for(int x=58+start;x<=72+start; x=x+2) { // Get remaining 8 bits
|
||||
if (RawSignal.Pulses[x+1]*RawSignal.Multiply > 550) return false;
|
||||
if(RawSignal.Pulses[x]*RawSignal.Multiply > 3000) {
|
||||
humidity = (humidity << 1) | 0x01;
|
||||
} else {
|
||||
humidity = (humidity << 1);
|
||||
}
|
||||
}
|
||||
//==================================================================================
|
||||
// Prevent repeating signals from showing up
|
||||
//==================================================================================
|
||||
if( (SignalHash!=SignalHashPrevious) || ((RepeatingTimer+3000) < millis()) ) { // 1000
|
||||
// not seen the RF packet recently
|
||||
if (bitstream == 0) return false; // Sanity check
|
||||
if (humidity==0) return false; // Sanity check
|
||||
} else {
|
||||
// already seen the RF packet recently
|
||||
return true;
|
||||
}
|
||||
//==================================================================================
|
||||
// Sort data
|
||||
rc = (bitstream >> 20) & 0xff;
|
||||
rc2= (bitstream >> 12) & 0xfb;
|
||||
if ( ((rc2)&0x08) != 0x08) return false; // needs to be 1
|
||||
temperature = (bitstream) & 0xfff;
|
||||
//fix 12 bit signed number conversion
|
||||
if ((temperature & 0x800) == 0x800) {
|
||||
temperature=4096-temperature; // fix for minus temperatures
|
||||
if (temperature > 0x258) return false; // temperature out of range ( > 60.0 degrees)
|
||||
temperature=temperature | 0x8000; // turn highest bit on for minus values
|
||||
} else {
|
||||
if (temperature > 0x258) return false; // temperature out of range ( > 60.0 degrees)
|
||||
}
|
||||
if (humidity > 99) return false; // Humidity out of range
|
||||
//==================================================================================
|
||||
// Output
|
||||
// ----------------------------------
|
||||
sprintf(pbuffer, "20;%02X;", PKSequenceNumber++);// Node and packet number
|
||||
Serial.print( pbuffer );
|
||||
// ----------------------------------
|
||||
Serial.print(F("Alecto V4;")); // Label
|
||||
sprintf(pbuffer, "ID=%02x%02x;", rc, rc2); // ID
|
||||
Serial.print( pbuffer );
|
||||
sprintf(pbuffer, "TEMP=%04x;", temperature);
|
||||
Serial.print( pbuffer );
|
||||
if (humidity < 99) { // Only report valid humidty values
|
||||
sprintf(pbuffer, "HUM=%02d;", humidity); // decimal value..
|
||||
Serial.print( pbuffer );
|
||||
}
|
||||
Serial.println();
|
||||
//==================================================================================
|
||||
RawSignal.Repeats=true; // suppress repeats of the same RF packet
|
||||
RawSignal.Number=0;
|
||||
return true;
|
||||
}
|
||||
#endif // PLUGIN_032
|
|
@ -0,0 +1,95 @@
|
|||
//#######################################################################################################
|
||||
//## This Plugin is only for use with the RFLink software package ##
|
||||
//## Plugin-33 Conrad ##
|
||||
//#######################################################################################################
|
||||
/*********************************************************************************************\
|
||||
* This plugin takes care of decoding Conrad Pool Thermomether model 9771
|
||||
*
|
||||
* Author : StuntTeam
|
||||
* 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!
|
||||
*********************************************************************************************
|
||||
* Changelog: v1.0 initial release
|
||||
*********************************************************************************************
|
||||
* Technical information:
|
||||
* Decodes signals from a Conrad Model 9771 Pool Thermometer, (80 pulses, 40 bits, 433 MHz).
|
||||
* Message Format:
|
||||
* AAAAAAAA BBBBBBBB CCCCCCCCCC DD EEEE FFFF GGGG
|
||||
* 00000000 00010010 1100101101 01 1001 0001 1001
|
||||
*
|
||||
* A = Always 0 ?
|
||||
* B = Device id ?
|
||||
* C = Temperature digits
|
||||
* D = Temperature ones
|
||||
* E = Temperature tens
|
||||
* F = Always 1?
|
||||
* G = Unknown
|
||||
*
|
||||
* Sample:
|
||||
* 20;8D;DEBUG;Pulses=80;Pulses(uSec)=1890,5760,1890,5730,1890,5760,1890,5730,1890,5760,1890,5760,1890,5760,1890,5760,1890,5760,1890,5760,1890,5760,5910,1830,1890,5640,1890,5760,5910,1830,1890,5640,5910,1830,1860,5640,5910,1830,1890,5610,5910,1830,5910,1830,5910,1830,1890,5400,5910,1830,1890,5610,1890,5760,5910,1830,5910,1830,1890,5520,1890,5760,5910,1860,1890,5610,1890,5760,1890,5760,5910,1830,1890,5610,5910,1830,5910,1830,1860,6990;
|
||||
\*********************************************************************************************/
|
||||
#define CONRAD_PULSECOUNT 80
|
||||
#define CONRAD_PULSEMAX 5000/RAWSIGNAL_SAMPLE_RATE
|
||||
#define CONRAD_PULSEMIN 2300/RAWSIGNAL_SAMPLE_RATE
|
||||
|
||||
#ifdef PLUGIN_033
|
||||
boolean Plugin_033(byte function, char *string) {
|
||||
if (RawSignal.Number != CONRAD_PULSECOUNT) return false;
|
||||
unsigned long bitstream=0L;
|
||||
unsigned int temperature=0;
|
||||
unsigned int rc=0;
|
||||
byte checksum=0;
|
||||
byte bitcount=0; // bit counter (counting first 8 bits that need
|
||||
//==================================================================================
|
||||
// get all 28 bits
|
||||
for(byte x=1;x <=CONRAD_PULSECOUNT-1;x+=2) {
|
||||
if (RawSignal.Pulses[x] > CONRAD_PULSEMAX) {
|
||||
if (RawSignal.Pulses[x+1] > CONRAD_PULSEMAX) if ( (x+1) < CONRAD_PULSECOUNT ) return false; // invalid pulse length
|
||||
if (bitcount > 7) {
|
||||
bitstream = (bitstream << 1) | 0x1;
|
||||
} else {
|
||||
return false; // first 8 bits should all be zeros
|
||||
}
|
||||
bitcount++;
|
||||
} else {
|
||||
if (RawSignal.Pulses[x] > CONRAD_PULSEMIN) return false; // invalid pulse length
|
||||
if (RawSignal.Pulses[x+1] < CONRAD_PULSEMIN) return false; // invalid pulse length
|
||||
if (bitcount > 7) bitstream = (bitstream << 1);
|
||||
bitcount++;
|
||||
}
|
||||
}
|
||||
//==================================================================================
|
||||
// Prevent repeating signals from showing up
|
||||
//==================================================================================
|
||||
Serial.println(bitstream,HEX);
|
||||
if( (SignalHash!=SignalHashPrevious) || (RepeatingTimer+1000<millis() ) || (SignalCRC != bitstream) ) {
|
||||
SignalCRC=bitstream; // not seen the RF packet recently
|
||||
if (bitstream == 0) return false; // Perform a sanity check
|
||||
} else {
|
||||
return true; // already seen the RF packet recently
|
||||
}
|
||||
//==================================================================================
|
||||
checksum = (bitstream >> 4) & 0x0f;
|
||||
if (checksum != 0x01) return false;
|
||||
|
||||
rc=(bitstream >> 24);
|
||||
temperature=(bitstream >> 14) & 0x3ff;
|
||||
temperature=temperature-500;
|
||||
//==================================================================================
|
||||
// Output
|
||||
// ----------------------------------
|
||||
sprintf(pbuffer, "20;%02X;", PKSequenceNumber++); // Node and packet number
|
||||
Serial.print( pbuffer );
|
||||
Serial.print(F("Conrad;")); // Label
|
||||
sprintf(pbuffer, "ID=%04x;", rc); // ID
|
||||
Serial.print( pbuffer );
|
||||
sprintf(pbuffer, "TEMP=%04x;", temperature);
|
||||
Serial.print( pbuffer );
|
||||
Serial.println();
|
||||
//==================================================================================
|
||||
RawSignal.Repeats=true; // suppress repeats of the same RF packet
|
||||
RawSignal.Number=0;
|
||||
return true;
|
||||
}
|
||||
#endif // PLUGIN_033
|
|
@ -0,0 +1,313 @@
|
|||
//#######################################################################################################
|
||||
//## This Plugin is only for use with the RFLink software package ##
|
||||
//## Plugin-34 Cresta ##
|
||||
//#######################################################################################################
|
||||
/*********************************************************************************************\
|
||||
* Dit protocol zorgt voor ontvangst van Cresta temperatuur weerstation buitensensoren
|
||||
* Tevens alle sensoren die het Cresta (Hideki) protocol volgen waaronder:
|
||||
* Hideki, TFA Nexus, Mebus, Irox, Irox-Pro X, Honeywell, Cresta TE923, TE923W, TE821W,
|
||||
* WXR810, DV928, Ventus W906
|
||||
*
|
||||
* Author : StuntTeam
|
||||
* 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!
|
||||
*********************************************************************************************
|
||||
* Changelog: v1.0 initial release
|
||||
*********************************************************************************************
|
||||
* Technical Information:
|
||||
* Decodes signals from a Cresta Weatherstation outdoor unit, (29 pulses, 28 bits, 433 MHz).
|
||||
* Message Format can be found at: http://members.upc.nl/m.beukelaar/Crestaprotocol.pdf
|
||||
* Thermo/Hygro: 10 bytes, seen as 128, 132, 134, 136, 138 pulses
|
||||
* Anemometer: 14 bytes
|
||||
* UV Index: 11 bytes
|
||||
* Rain: 9 bytes, seen as 132, 136 pulses
|
||||
\*********************************************************************************************/
|
||||
#define CRESTA_MIN_PULSECOUNT 124 // unknown until we have a collection of all packet types but this seems to be the minimum
|
||||
#define CRESTA_MAX_PULSECOUNT 284 // unknown until we have a collection of all packet types
|
||||
#define CRESTA_PULSEMID 700/RAWSIGNAL_SAMPLE_RATE
|
||||
|
||||
#ifdef PLUGIN_034
|
||||
byte Plugin_034_reverseBits(byte data);
|
||||
byte Plugin_034_WindDirSeg(byte data);
|
||||
|
||||
boolean Plugin_034(byte function, char *string){
|
||||
if ((RawSignal.Number < CRESTA_MIN_PULSECOUNT) || (RawSignal.Number > CRESTA_MAX_PULSECOUNT) ) return false;
|
||||
|
||||
int sensor_data=0;
|
||||
int windtemp=0;
|
||||
int windchill=0;
|
||||
int windgust=0;
|
||||
int windspeed=0;
|
||||
int winddirection=0;
|
||||
int uv=0;
|
||||
|
||||
byte checksum=0;
|
||||
byte data[18];
|
||||
byte length=0;
|
||||
byte channel=0;
|
||||
int units=0;
|
||||
byte battery=0;
|
||||
|
||||
byte bytecounter=0; // used for counting the number of received bytes
|
||||
byte bitcounter=0; // counts number of received bits (converted from pulses)
|
||||
int pulseposition=1; // first pulse is always empty
|
||||
byte halfbit=0; // high pulse = 1, 2 low pulses = 0, halfbit keeps track of low pulses
|
||||
byte parity=0; // to calculate byte parity
|
||||
// ==================================================================================
|
||||
// get bytes and determine if byte parity is set correctly for the cresta protocol on the fly
|
||||
do {
|
||||
//if(RawSignal.Pulses[pulseposition]*RawSignal.Multiply > 700) { // high value = 1 bit
|
||||
if(RawSignal.Pulses[pulseposition] > CRESTA_PULSEMID) { // high value = 1 bit
|
||||
if (halfbit==1) { // cant receive a 1 bit after a single low value
|
||||
return false; // pulse error, must not be a Cresta packet or reception error
|
||||
}
|
||||
if (bitcounter==8) {
|
||||
if (parity != 1) { // now receiving parity bit
|
||||
return false; // parity error, must not be a Cresta packet or reception error
|
||||
} else {
|
||||
bitcounter=0; // reset for next byte
|
||||
parity=0; // reset for next byte
|
||||
halfbit=0; // wait for next first low or high pulse
|
||||
bytecounter++; // 1 byte received
|
||||
}
|
||||
} else {
|
||||
data[bytecounter] = (data[bytecounter] << 1) | 0x1; // 1 bit
|
||||
parity=parity ^1; // update parity
|
||||
bitcounter++; // received a bit
|
||||
halfbit=0; // waiting for first low or a new high pulse
|
||||
}
|
||||
} else {
|
||||
if (halfbit == 0) { // 2 times a low value = 0 bit
|
||||
halfbit=1; // first half received
|
||||
} else {
|
||||
if (bitcounter==8) {
|
||||
if (parity != 0) { // now receiving parity bit
|
||||
return false; // parity error, must not be a Cresta packet or reception error
|
||||
} else {
|
||||
bitcounter=0; // reset for next byte
|
||||
parity=0; // reset for next byte
|
||||
halfbit=0; // wait for next first low or high pulse
|
||||
bytecounter++; // 1 byte received
|
||||
}
|
||||
} else {
|
||||
data[bytecounter] = (data[bytecounter] << 1); // 0 bit
|
||||
parity=parity ^0; // update parity
|
||||
bitcounter++; // received a bit
|
||||
halfbit=0; // wait for next first low or high pulse
|
||||
}
|
||||
}
|
||||
}
|
||||
pulseposition++; // point to next pulse
|
||||
if (pulseposition > RawSignal.Number) break; // reached the end? done processing
|
||||
} while(bytecounter < 16); // receive maximum number of bytes from pulses
|
||||
// ==================================================================================
|
||||
// all bytes received, make sure checksum is okay
|
||||
// ==================================================================================
|
||||
for (byte i=0;i<bytecounter;i++) {
|
||||
data[i] = Plugin_034_reverseBits( data[i] );
|
||||
}
|
||||
// get packet length
|
||||
length=data[2] & 0x3f; // drop bits 6 and 7
|
||||
length >>= 1; // drop bit 0
|
||||
if (length > 20) return false; // Additional check for illegal packet lengths to protect against false positives.
|
||||
if (length == 0) return false; // Additional check for illegal packet lengths to protect against false positives.
|
||||
// Checksum: XOR of all bytes from byte 1 till byte length+2, should result in 0
|
||||
checksum=0;
|
||||
for (byte i=1;i< length+2 ;i++){
|
||||
checksum=checksum^data[i];
|
||||
}
|
||||
if (checksum != 0) return false;
|
||||
// ==================================================================================
|
||||
// now process the various sensor types
|
||||
// ==================================================================================
|
||||
if ( data[1] > 0x1f && data[1] < 0x40) channel=1;
|
||||
if ( data[1] > 0x3f && data[1] < 0x60) channel=2;
|
||||
if ( data[1] > 0x5f && data[1] < 0x80) channel=3;
|
||||
if ( data[1] > 0x7f && data[1] < 0xa0) channel=1; // no channel settings on Anemometer/rainmeter and uvsensor
|
||||
if ( data[1] > 0x9f && data[1] < 0xc0) channel=4;
|
||||
if ( data[1] > 0xbf && data[1] < 0xE0) channel=5;
|
||||
data[3]=(data[3])&0x1f;
|
||||
//==================================================================================
|
||||
// Prevent repeating signals from showing up
|
||||
//==================================================================================
|
||||
unsigned long tempval=data[3];
|
||||
tempval=((tempval)<<16)+((data[1])<<8)+channel;
|
||||
if((SignalHash!=SignalHashPrevious) || (RepeatingTimer<millis() && SignalCRC != tempval) || (SignalCRC != tempval) ) {
|
||||
SignalCRC=tempval; // not seen the RF packet recently
|
||||
} else {
|
||||
return true; // already seen the RF packet recently
|
||||
}
|
||||
// ----------------------------------
|
||||
battery=(data[2])>>6;
|
||||
// ----------------------------------
|
||||
if (data[3] == 0x0c ) { // Anemometer
|
||||
units=((data[4]>>4)*10) + (data[4]&0x0f) ;
|
||||
sensor_data=((data[5]&0x3f) * 100) + units;
|
||||
if ((data[5] & 0x80) != 0x80) {
|
||||
sensor_data = sensor_data | 0x8000; // set highest bit (minus bit)
|
||||
}
|
||||
windtemp=sensor_data;
|
||||
|
||||
units=((data[6]>>4)*10) + (data[6]&0x0f) ;
|
||||
sensor_data=((data[7]&0x3f) * 100) + units;
|
||||
if ((data[7] & 0x80) != 0x80) {
|
||||
sensor_data = sensor_data | 0x8000; // set highest bit (minus bit)
|
||||
}
|
||||
windchill=sensor_data;
|
||||
|
||||
windspeed=((data[9]&0x0F)*100) + ((data[8]>>4)*10) + (data[8]&0x0F);
|
||||
windgust=((data[10]>>4)*100) + ((data[10]&0x0F)*10) + (data[9]>>4);
|
||||
|
||||
//windspeed = (data[9] << 8) + data[8];
|
||||
//windgust = (data[10] << 4) + ( (data[9] &0xf0) >> 4 );
|
||||
|
||||
winddirection = Plugin_034_WindDirSeg( ((data[11] &0xf0) >> 4) );
|
||||
winddirection = winddirection & 0x0f; // make sure we dont get overflows
|
||||
//==================================================================================
|
||||
// Output
|
||||
// ----------------------------------
|
||||
Serial.print("20;");
|
||||
PrintHexByte(PKSequenceNumber++);
|
||||
Serial.print(F(";Cresta;ID=")); // Label
|
||||
PrintHexByte(data[1]);
|
||||
PrintHexByte(channel);
|
||||
// ----------------------------------
|
||||
sprintf(pbuffer, ";WINDIR=%04d;", winddirection);
|
||||
Serial.print( pbuffer );
|
||||
sprintf(pbuffer, "WINSP=%04x;", windspeed);
|
||||
Serial.print( pbuffer );
|
||||
sprintf(pbuffer, "WINGS=%04x;", windgust);
|
||||
Serial.print( pbuffer );
|
||||
sprintf(pbuffer, "WINTMP=%04x;", windtemp);
|
||||
Serial.print( pbuffer );
|
||||
sprintf(pbuffer, "WINCHL=%04x;", windchill);
|
||||
Serial.print( pbuffer );
|
||||
if ( battery != 0) {
|
||||
Serial.print(F("BAT=OK;")); // Label
|
||||
} else {
|
||||
Serial.print(F("BAT=LOW;")); // Label
|
||||
}
|
||||
Serial.println();
|
||||
//==================================================================================
|
||||
} else
|
||||
// ----------------------------------
|
||||
if (data[3] == 0x0d ) { // UV Sensor
|
||||
units=((data[4]>>4)*10) + (data[4]&0x0f) ;
|
||||
sensor_data=((data[5]&0x3f) * 100) + units;
|
||||
if ((data[5] & 0x80) != 0x80) {
|
||||
sensor_data = sensor_data | 0x8000; // set highest bit (minus bit)
|
||||
}
|
||||
// UV sensor reports the temperature but does not report negative values!, skip temperature info?
|
||||
uv = ((data[8] & 0x0f)<<8)+data[7];
|
||||
//==================================================================================
|
||||
// Output
|
||||
// ----------------------------------
|
||||
Serial.print("20;");
|
||||
PrintHexByte(PKSequenceNumber++);
|
||||
Serial.print(F(";Cresta;ID=")); // Label
|
||||
PrintHexByte(data[1]);
|
||||
PrintHexByte(channel);
|
||||
// ----------------------------------
|
||||
sprintf(pbuffer, ";TEMP=%04x;", sensor_data);
|
||||
Serial.print( pbuffer );
|
||||
sprintf(pbuffer, "UV=%04x;", uv);
|
||||
Serial.print( pbuffer );
|
||||
if ( battery != 0) {
|
||||
Serial.print(F("BAT=OK;")); // Label
|
||||
} else {
|
||||
Serial.print(F("BAT=LOW;")); // Label
|
||||
}
|
||||
Serial.println();
|
||||
//==================================================================================
|
||||
} else // 9F 80 CC 4E 00 00 66 64
|
||||
// ---------------------------------- // 9f 80 cc 4e 01 00 66 65
|
||||
if (data[3] == 0x0e ) { // Rain meter // 9F 80 CC 4E 76 00 66 12
|
||||
sensor_data = (data[5]<<8)+data[4]; // 80=rain 4e=>0E = rain
|
||||
sensor_data=sensor_data*7; // 66 = always 66 rain units * 0.7 = mm.
|
||||
//==================================================================================
|
||||
// Output
|
||||
// ----------------------------------
|
||||
Serial.print("20;");
|
||||
PrintHexByte(PKSequenceNumber++);
|
||||
Serial.print(F(";Cresta;ID=")); // Label
|
||||
PrintHexByte(data[1]);
|
||||
PrintHexByte(channel);
|
||||
// ----------------------------------
|
||||
sprintf(pbuffer, ";RAIN=%04x;", sensor_data);
|
||||
Serial.print( pbuffer );
|
||||
if ( battery != 0) {
|
||||
Serial.print(F("BAT=OK;"));
|
||||
} else {
|
||||
Serial.print(F("BAT=LOW;"));
|
||||
}
|
||||
Serial.println();
|
||||
//==================================================================================
|
||||
} else
|
||||
// ----------------------------------
|
||||
if (data[3] == 0x1e ) { // Thermo/Hygro
|
||||
units=((data[4]>>4)*10) + (data[4]&0x0f) ;
|
||||
sensor_data=((data[5]&0x3f) * 100) + units;
|
||||
if ((data[5] & 0x80) != 0x80) {
|
||||
sensor_data = sensor_data | 0x8000; // set highest bit (minus bit)
|
||||
}
|
||||
//==================================================================================
|
||||
// Output
|
||||
// ----------------------------------
|
||||
Serial.print("20;");
|
||||
PrintHexByte(PKSequenceNumber++);
|
||||
Serial.print(F(";Cresta;ID=")); // Label
|
||||
PrintHexByte(data[1]);
|
||||
PrintHexByte(channel);
|
||||
// ----------------------------------
|
||||
sprintf(pbuffer, ";TEMP=%04x;", sensor_data);
|
||||
Serial.print( pbuffer );
|
||||
sprintf(pbuffer, "HUM=%02x;", data[6]);
|
||||
Serial.print( pbuffer );
|
||||
if ( battery != 0) {
|
||||
Serial.print(F("BAT=OK;"));
|
||||
} else {
|
||||
Serial.print(F("BAT=LOW;"));
|
||||
}
|
||||
Serial.println();
|
||||
//==================================================================================
|
||||
} else {
|
||||
//==================================================================================
|
||||
// Output
|
||||
// ----------------------------------
|
||||
Serial.print("20;");
|
||||
PrintHexByte(PKSequenceNumber++);
|
||||
Serial.print(F(";Cresta;DEBUG;ID=")); // Label
|
||||
PrintHexByte(data[1]);
|
||||
PrintHexByte(channel);
|
||||
// ----------------------------------
|
||||
PrintHex8( data, length+2);
|
||||
Serial.print(F(";"));
|
||||
Serial.println();
|
||||
//==================================================================================
|
||||
}
|
||||
RawSignal.Repeats=true; // suppress repeats of the same RF packet
|
||||
RawSignal.Number=0;
|
||||
return true;
|
||||
}
|
||||
|
||||
// *********************************************************************************************
|
||||
// * Reverse all bits in a byte
|
||||
// *********************************************************************************************
|
||||
byte Plugin_034_reverseBits(byte data) {
|
||||
byte b = data;
|
||||
for (byte i = 0; i < 8; ++i) {
|
||||
data = (data << 1) | (b & 1);
|
||||
b >>= 1;
|
||||
}
|
||||
return data;
|
||||
}
|
||||
|
||||
byte Plugin_034_WindDirSeg(byte data) {
|
||||
// Encrypted using: a=-a&0xf; b=a^(a>>1);
|
||||
data ^= (data & 8) >> 1; /* Solve bit 2 */
|
||||
data ^= (data & 4) >> 1; /* Solve bit 1 */
|
||||
data ^= (data & 2) >> 1; /* Solve bit 0 */
|
||||
return -data & 0xf;
|
||||
}
|
||||
#endif // PLUGIN_034
|
|
@ -0,0 +1,110 @@
|
|||
//#######################################################################################################
|
||||
//## This Plugin is only for use with the RFLink software package ##
|
||||
//## Plugin-35 Imagintronix ##
|
||||
//#######################################################################################################
|
||||
/*********************************************************************************************\
|
||||
* This plugin takes care of decoding Imagintronix sensors
|
||||
*
|
||||
* Author : StuntTeam
|
||||
* 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!
|
||||
*********************************************************************************************
|
||||
* Changelog: v1.0 initial release
|
||||
*********************************************************************************************
|
||||
* Technical information:
|
||||
*
|
||||
* ~0.5ms high puls followed by ~1ms pause = high
|
||||
* ~1.5ms high puls followed by ~1ms pause = low
|
||||
*
|
||||
* Message Format:
|
||||
* 11111111 01010101 00000101 01000101 11111111 10011110
|
||||
* FF550545FF9E
|
||||
* AABCDDEEFFGG
|
||||
*
|
||||
* A = Preamble, always FF
|
||||
* B = TX type, always 5
|
||||
* C = Address (5/6/7) > low 2 bits = 1/2/3
|
||||
* D = Soil moisture 05%
|
||||
* E = temperature
|
||||
* F = security code, always F
|
||||
* G = Checksum 55+05+45+FF=19E CRC value = 9E
|
||||
*
|
||||
* Sample:
|
||||
* 20;02;DEBUG;Pulses=96;Pulses(uSec)=390,870,420,870,420,870,420,870,420,870,420,870,420,870,420,870,1260,870,420,870,1260,870,420,870, 1230,870,420,870,1260,870,420,870,1260,870,1260,870,1260,870,1230,870,1260,870,420,870,1260,870,420,870,1260,870,420,870,1260,870,1260,870,1260,870,420,870,1260,870,420,870,420,870,420,870,420,870,420,870,420,870,420,870,420,870,420,870,420,870,1230,870,1260,870,420,870,420,870,420,840,420,840,1260,6990;
|
||||
* 111111110101010100000101010001011111111110011110
|
||||
\*********************************************************************************************/
|
||||
#define IMAGINTRONIX_PULSECOUNT 96
|
||||
#define IMAGINTRONIX_PULSEMID 1000/RAWSIGNAL_SAMPLE_RATE
|
||||
#define IMAGINTRONIX_PULSESHORT 550/RAWSIGNAL_SAMPLE_RATE
|
||||
|
||||
#ifdef PLUGIN_035
|
||||
boolean Plugin_035(byte function, char *string) {
|
||||
if (RawSignal.Number != IMAGINTRONIX_PULSECOUNT) return false;
|
||||
unsigned int temperature=0;
|
||||
unsigned int rc=0;
|
||||
|
||||
byte checksum=0;
|
||||
byte data[8];
|
||||
unsigned long bitstream=0L;
|
||||
//==================================================================================
|
||||
byte bytecounter=0; // used for counting the number of received bytes
|
||||
byte bitcounter=0; // counts number of received bits (converted from pulses)
|
||||
// get bits
|
||||
for(byte x=1;x < IMAGINTRONIX_PULSECOUNT;x=x+2) {
|
||||
if (RawSignal.Pulses[x] > IMAGINTRONIX_PULSEMID) { // long pulse = 0 bit
|
||||
if (x < 95) if ((RawSignal.Pulses[x+1] > IMAGINTRONIX_PULSEMID) || (RawSignal.Pulses[x+1] < IMAGINTRONIX_PULSESHORT)) return false;
|
||||
data[bytecounter] = (data[bytecounter] << 1); // 0 bit
|
||||
bitcounter++; // received a bit
|
||||
} else { // Short pulse = 1 bit
|
||||
if (RawSignal.Pulses[x] > IMAGINTRONIX_PULSESHORT) return false; // Short pulse too long?
|
||||
if (x < 95) if ((RawSignal.Pulses[x+1] > IMAGINTRONIX_PULSEMID) || (RawSignal.Pulses[x+1] < IMAGINTRONIX_PULSESHORT)) return false;
|
||||
data[bytecounter] = (data[bytecounter] << 1) | 0x1; // 1 bit
|
||||
bitcounter++; // received a bit
|
||||
}
|
||||
// prepare for next bit/byte
|
||||
if (bitcounter==8) { // received 8 bits?
|
||||
bitcounter=0; // reset for next byte
|
||||
bytecounter++; // byte received, increase counter
|
||||
if (bytecounter > 7) return false; // overflow, should not happen
|
||||
}
|
||||
}
|
||||
//==================================================================================
|
||||
// Verify packet and calculate checksum
|
||||
//==================================================================================
|
||||
if (data[0] != 0xff) return false;
|
||||
checksum=data[1]+data[2]+data[3]+data[4];
|
||||
if (((checksum)&0xff) != data[5]) return false;
|
||||
if ( (data[1] >>4) != 0x5) return false;
|
||||
if (data[4] != 0xff) return false;
|
||||
//==================================================================================
|
||||
// Prevent repeating signals from showing up
|
||||
//==================================================================================
|
||||
if( (SignalHash!=SignalHashPrevious) || (RepeatingTimer+1000<millis()) ) {
|
||||
//SignalCRC=bitstream; // not seen the RF packet recently
|
||||
} else {
|
||||
return true; // already seen the RF packet recently
|
||||
}
|
||||
//==================================================================================
|
||||
rc=(data[1])&0x03;
|
||||
temperature=(data[3]) << 4;
|
||||
temperature=temperature/2;
|
||||
//==================================================================================
|
||||
// Output
|
||||
// ----------------------------------
|
||||
sprintf(pbuffer, "20;%02X;", PKSequenceNumber++); // Node and packet number
|
||||
Serial.print( pbuffer );
|
||||
Serial.print(F("Imagintronix;")); // Label
|
||||
sprintf(pbuffer, "ID=%04x;", rc); // ID
|
||||
Serial.print( pbuffer );
|
||||
sprintf(pbuffer, "TEMP=%04x;", temperature);
|
||||
Serial.print( pbuffer );
|
||||
sprintf(pbuffer, "HUM=%02x;", data[2]);
|
||||
Serial.print( pbuffer );
|
||||
Serial.println();
|
||||
//==================================================================================
|
||||
RawSignal.Repeats=true; // suppress repeats of the same RF packet
|
||||
RawSignal.Number=0;
|
||||
return true;
|
||||
}
|
||||
#endif // PLUGIN_035
|
|
@ -0,0 +1,117 @@
|
|||
//#######################################################################################################
|
||||
//## This Plugin is only for use with the RFLink software package ##
|
||||
//## Plugin-40 Mebus ##
|
||||
//#######################################################################################################
|
||||
/*********************************************************************************************\
|
||||
* This plugin takes care of decoding Mebus weatherstation outdoor sensors
|
||||
* It concerns Mebus sensors that are not following the Cresta (Hideki) protocol
|
||||
* Also sold as Stacja Pogody WS-9941-M
|
||||
*
|
||||
* Author : StuntTeam
|
||||
* 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!
|
||||
*********************************************************************************************
|
||||
* Changelog: v1.0 initial release
|
||||
*********************************************************************************************
|
||||
* Technical information:
|
||||
* Decodes signals from a Mebus Weatherstation outdoor unit, (58 pulses, 28 bits, 433 MHz).
|
||||
* Mebus Message Format:
|
||||
* AAAA BBBB BBBB CCCC CCCC CCCC DDEF
|
||||
*
|
||||
* A = Checksum value AAAA=((BBBB+BBBB+CCCC+CCCC+DDEF)-1)&0x0f
|
||||
* B = Changes after each reset, no change during normal operation. (Device 'Session' ID)
|
||||
* C = Temperature (21.5 degrees is shown as decimal value 215, minus values have the high bit set and need to be subtracted from a base value of 4096)
|
||||
* D = Channel number 1/2/3
|
||||
* E = Always 1
|
||||
* F = 0 when "normal" data transmit, 1 when "requested" data transmit (TX button press)
|
||||
*
|
||||
* 20;DE;DEBUG;Pulses=58;Pulses(uSec)=525,1800,350,1800,350,4275,350,1800,350,4275,350,4275,350,4275,350,1800,350,4250,350,4275,350,1800,350,4250,350,1800,350,1800,350,1800,350,1800,350,4275,350,4275,350,4250,350,1800,350,1800,350,1800,350,4275,350,4250,350,1800,350,4275,350,4275,350,4250,350;
|
||||
* 20;80;DEBUG;Pulses=58;Pulses(uSec)=450,4450,375,4450,375,4450,375,4450,375,1875,375,4450,375,4450,375,1875,375,1875,375,4425,375,4425,375,4425,375,1875,375,1875,375,1875,375,4425,375,1875,375,1875,375,1875,375,1875,375,4450,375,4450,375,1875,375,1875,375,1875,375,4450,375,4425,375,1875,375;
|
||||
* 20;81;Mebus;ID=6701;TEMP=010c;
|
||||
\*********************************************************************************************/
|
||||
// ==================================================================================
|
||||
// MEBUS bit packets
|
||||
// 0000 1101 1001 0000 1100 1000 0111
|
||||
// 0100 1101 1001 0000 1101 1100 0110
|
||||
// 0100 1101 1001 0000 1100 1101 0110
|
||||
// 1001 1101 1001 0000 1101 1100 1011
|
||||
// 1011 1101 1001 0001 0000 1111 0110 27.1
|
||||
// 0010 0110 1110 0000 0000 1001 0110 0.9
|
||||
// 0011 0110 1110 1111 1000 0011 0110 -12.5 (1111 1000 0011=3971, 4096-3971=125
|
||||
// |----------|----------> temperature 0 - 51.1
|
||||
// |-|---------------------> set when minus temperatures -51.2 - 0
|
||||
// ==================================================================================
|
||||
#define MEBUS_PULSECOUNT 58
|
||||
|
||||
#ifdef PLUGIN_040
|
||||
boolean Plugin_040(byte function, char *string) {
|
||||
if (RawSignal.Number != MEBUS_PULSECOUNT) return false;
|
||||
unsigned long bitstream=0L;
|
||||
unsigned int temperature=0;
|
||||
byte rc=0;
|
||||
byte checksum=0;
|
||||
byte data[7];
|
||||
byte channel=0;
|
||||
//==================================================================================
|
||||
// get all 28 bits
|
||||
for(byte x=2;x <=MEBUS_PULSECOUNT-2;x+=2) {
|
||||
if (RawSignal.Pulses[x+1]*RawSignal.Multiply > 550) return false; // make sure inbetween pulses are not too long
|
||||
if (RawSignal.Pulses[x]*RawSignal.Multiply > 3400) {
|
||||
bitstream = (bitstream << 1) | 0x1;
|
||||
} else {
|
||||
if (RawSignal.Pulses[x]*RawSignal.Multiply > 2000) return false; // invalid pulse length
|
||||
if (RawSignal.Pulses[x]*RawSignal.Multiply < 1500) return false; // invalid pulse length
|
||||
bitstream = (bitstream << 1);
|
||||
}
|
||||
}
|
||||
//==================================================================================
|
||||
// Prevent repeating signals from showing up
|
||||
//==================================================================================
|
||||
if( (SignalHash!=SignalHashPrevious) || (RepeatingTimer+1000<millis() && SignalCRC != bitstream) || (SignalCRC != bitstream) ) {
|
||||
SignalCRC=bitstream; // not seen the RF packet recently
|
||||
if (bitstream == 0) return false; // Perform a sanity check
|
||||
} else {
|
||||
return true; // already seen the RF packet recently
|
||||
}
|
||||
//==================================================================================
|
||||
data[0] = (bitstream >> 24) & 0x0f; // prepare nibbles from bit stream
|
||||
data[1] = (bitstream >> 20) & 0x0f;
|
||||
data[2] = (bitstream >> 16) & 0x0f;
|
||||
data[3] = (bitstream >> 12) & 0x0f;
|
||||
data[4] = (bitstream >> 8) & 0x0f;
|
||||
data[5] = (bitstream >> 4) & 0x0f;
|
||||
data[6] = (bitstream >> 0) & 0x0f;
|
||||
//==================================================================================
|
||||
// first perform a checksum check to make sure the packet is a valid mebus packet
|
||||
checksum=data[1]+data[2]+data[3]+data[4]+data[5]+data[6];
|
||||
checksum=(checksum-1)&0xf;
|
||||
if (checksum != data[0]) return false;
|
||||
//==================================================================================
|
||||
rc=(data[1]<<4) + data[2];
|
||||
channel=(data[6])>>2;
|
||||
temperature=(data[3]<<8)+(data[4]<<4)+data[5];
|
||||
if (temperature > 3000) {
|
||||
temperature=4096-temperature; // fix for minus temperatures
|
||||
if (temperature > 0x258) return false; // temperature out of range ( > -60.0 degrees)
|
||||
temperature=temperature | 0x8000; // turn highest bit on for minus values
|
||||
} else {
|
||||
if (temperature > 0x258) return false; // temperature out of range ( > 60.0 degrees)
|
||||
}
|
||||
//==================================================================================
|
||||
// Output
|
||||
// ----------------------------------
|
||||
sprintf(pbuffer, "20;%02X;", PKSequenceNumber++); // Node and packet number
|
||||
Serial.print( pbuffer );
|
||||
Serial.print(F("Mebus;")); // Label
|
||||
sprintf(pbuffer, "ID=%02x%02x;", rc, channel);// ID
|
||||
Serial.print( pbuffer );
|
||||
sprintf(pbuffer, "TEMP=%04x;", temperature);
|
||||
Serial.print( pbuffer );
|
||||
Serial.println();
|
||||
//==================================================================================
|
||||
RawSignal.Repeats=true; // suppress repeats of the same RF packet
|
||||
RawSignal.Number=0;
|
||||
return true;
|
||||
}
|
||||
#endif // PLUGIN_040
|
|
@ -0,0 +1,250 @@
|
|||
//#######################################################################################################
|
||||
//## This Plugin is only for use with the RFLink software package ##
|
||||
//## Plugin-43 LaCrosse ##
|
||||
//#######################################################################################################
|
||||
/*********************************************************************************************\
|
||||
* This plugin takes care of decoding LaCrosse weatherstation outdoor sensors
|
||||
* It also works for all non LaCrosse sensors that follow this protocol.
|
||||
* WS7000-15: Anemometer, WS7000-16: Rain precipitation, WS2500-19: Brightness Luxmeter, WS7000-20: Thermo/Humidity/Barometer
|
||||
*
|
||||
* Author : StuntTeam
|
||||
* 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!
|
||||
*********************************************************************************************
|
||||
* Changelog: v1.0 initial release
|
||||
*********************************************************************************************
|
||||
* Meteo Sensor: (162 pulses)
|
||||
* Each frame is 80 bits long. It is composed of:
|
||||
* 10 bits of 0 (preamble)
|
||||
* 14 blocks of four bits separated by a 1 bit to be checked and skipped
|
||||
*
|
||||
* 0100 0111 1000 0101 0010 0100 0000 0011 0001 0001 1000 1101 1110 1011
|
||||
* aaaa bbbb cccc cccc cccc dddd dddd dddd eeee eeee eeee ffff gggg hhhh
|
||||
*
|
||||
* a = sensor type (04=Meteo sensor)
|
||||
* b = sensor address
|
||||
* c = temperature BCD, reversed
|
||||
* d = humidity BCD, reversed
|
||||
* e = air pressure, BCD reversed + 200 offset in hPa
|
||||
* f = unknown?
|
||||
* g = xor value
|
||||
* h = checksum value
|
||||
*
|
||||
* Sample:
|
||||
* 20;07;DEBUG;Pulses=162;Pulses(uSec)=825,275,750,275,750,300,750,300,750,300,750,275,750,275,750,300,750,300,750,300,250,800,725,300,750,300,250,800,725,300,225,800,225,800,250,800,250,800,725,300,250,800,725,300,750,300,725,300,250,800,250,800,225,800,750,300,250,800,725,300,250,800,725,300,250,800,725,300,725,300,250,800,725,300,725,300,250,800,725,300,250,800,725,300,725,300,725,300,725,300,250,800,225,800,225,800,725,300,725,300,225,800,225,800,725,300,725,300,725,300,250,800,250,800,725,300,725,300,725,300,250,800,725,300,725,300,725,300,225,800,225,800,225,800,725,300,225,800,225,800,250,800,725,300,225,800,225,800,225,800,250,800,250,800,225,800,725,300,225,800,225,600;
|
||||
* 1010101010101010101001101001100101010110011010100101011001100110011010011010011001101010100101011010010110101001011010100110101001010110010101100101010101011001 00
|
||||
* 0000000000 1 0010 1 1110 1 0001 1 1010 1 0100 1 0010 1 0000 1 1100 1 1000 1 1000 1 0001 1 1011 1 0111 1 1101 0
|
||||
* 0010 1110 0001 1010 0100 0010 0000 1100 1000 1000 0001 1011 0111 1101
|
||||
* 0100 0111 1000 0101 0010 0100 0000 0011 0001 0001 1000 1101 1110 1011
|
||||
* 4 7 852 403 118 D E B
|
||||
* 25.8 30.4 811+200
|
||||
* --------------------------------------------------------------------------------------------
|
||||
* Rain Packet: (92 pulses)
|
||||
* Each frame is 46 bits long. It is composed of:
|
||||
* 10 bits of 0 (preamble)
|
||||
* 7 blocks of four bits separated by a 1 bit to be checked and skipped
|
||||
*
|
||||
* The 1st bit of each word is LSB, so we have to reverse the 4 bits of each word.
|
||||
* Example
|
||||
* 0000000000 0010 1111 1011 0010 1011 1111 1101
|
||||
* aaaa bbbb ccc1 ccc2 ccc3 dddd eeee
|
||||
* 2 F B 2 B F D
|
||||
*
|
||||
* a = sensor type (2=Rain meter)
|
||||
* b = sensor address
|
||||
* c = rain data (LSB thus the right order is c3 c2 c1)
|
||||
* d = Check Xor : (2 ^ F ^ B ^ 2 ^ B ^ F) = 0
|
||||
* e = Check Sum : (const5 + 2 + F + B + 2 + B + F) and F = D
|
||||
* --------------------------------------------------------------------------------------------
|
||||
* Wind packet: (122 pulses)
|
||||
* Each frame is composed of:
|
||||
* 10bits of 0 (preamble)
|
||||
* 10 blocks of four bits separated by a bit 1 to be checked and skipped
|
||||
*
|
||||
* The 1st bit of each word is LSB, so we have to reverse the 4 bits of each word.
|
||||
* Example
|
||||
* 0000000000 0011 0111 0101 0000 0001 0101 0100 0111 0110 1011
|
||||
* aaaa bbbb cccc cccc cccc dddd dddd ddee ffff gggg
|
||||
* 3 7 5 0 1 5 4 1 3 6 B
|
||||
*
|
||||
* a = sensor type (2=Rain meter)
|
||||
* b = sensor address
|
||||
* c = speed
|
||||
* d = direction
|
||||
* f = Check Xor
|
||||
* g = Check Sum
|
||||
* --------------------------------------------------------------------------------------------
|
||||
* UV packet (132 pulses)
|
||||
\*********************************************************************************************/
|
||||
#define LACROSSE41_PULSECOUNT1 92 // Rain sensor
|
||||
#define LACROSSE41_PULSECOUNT2 162 // Meteo sensor
|
||||
#define LACROSSE41_PULSECOUNT3 122 // Wind sensor
|
||||
#define LACROSSE41_PULSECOUNT4 132 // Brightness sensor
|
||||
|
||||
#define LACROSSE41_PULSEMID 500/RAWSIGNAL_SAMPLE_RATE
|
||||
|
||||
#ifdef PLUGIN_041
|
||||
boolean Plugin_041(byte function, char *string) {
|
||||
boolean success=false;
|
||||
if ( (RawSignal.Number != LACROSSE41_PULSECOUNT1) && (RawSignal.Number != LACROSSE41_PULSECOUNT2) &&
|
||||
(RawSignal.Number != LACROSSE41_PULSECOUNT3) && (RawSignal.Number != LACROSSE41_PULSECOUNT4) ) return false;
|
||||
|
||||
unsigned long bitstream1=0L; // holds first 16 bits
|
||||
unsigned long bitstream2=0L; // holds last 28 bits
|
||||
|
||||
int sensor_data=0;
|
||||
|
||||
byte checksum=0;
|
||||
|
||||
byte bitcounter=0; // counts number of received bits (converted from pulses)
|
||||
byte bytecounter=0; // used for counting the number of received bytes
|
||||
byte data[18];
|
||||
//==================================================================================
|
||||
// Check preamble
|
||||
for(int x=1;x<20;x+=2) {
|
||||
if ((RawSignal.Pulses[x] < LACROSSE41_PULSEMID) || (RawSignal.Pulses[x+1] > LACROSSE41_PULSEMID) ) {
|
||||
return false; // bad preamble bit detected, abort
|
||||
}
|
||||
}
|
||||
if ((RawSignal.Pulses[21] > LACROSSE41_PULSEMID) || (RawSignal.Pulses[22] < LACROSSE41_PULSEMID) ) {
|
||||
return false; // There should be a 1 bit after the preamble
|
||||
}
|
||||
// get bits/nibbles
|
||||
for(int x=23;x<RawSignal.Number-2;x+=2) {
|
||||
if (RawSignal.Pulses[x] < LACROSSE41_PULSEMID) { // 1 bit
|
||||
data[bytecounter] = ((data[bytecounter] >> 1) | 0x08); // 1 bit, store in reversed bit order
|
||||
} else {
|
||||
data[bytecounter] = ((data[bytecounter] >> 1)&0x07); // 0 bit, store in reversed bit order
|
||||
}
|
||||
bitcounter++;
|
||||
if (bitcounter == 4) {
|
||||
x=x+2;
|
||||
if (x > RawSignal.Number-2) break; // dont check the last marker
|
||||
if ((RawSignal.Pulses[x] > LACROSSE41_PULSEMID) || (RawSignal.Pulses[x+1] < LACROSSE41_PULSEMID) ) {
|
||||
return false; // There should be a 1 bit after each nibble
|
||||
}
|
||||
bitcounter=0;
|
||||
bytecounter++;
|
||||
if (bytecounter > 17) return false; // received too many nibbles/bytes, abort
|
||||
}
|
||||
}
|
||||
//==================================================================================
|
||||
// all bytes received, make sure checksum is okay
|
||||
//==================================================================================
|
||||
// check xor value
|
||||
checksum=0;
|
||||
for (byte i=0;i<bytecounter;i++){
|
||||
checksum=checksum^data[i];
|
||||
}
|
||||
if (checksum !=0) return false; // all (excluding last) nibbles xored must result in 0
|
||||
// check checksum value
|
||||
checksum=5;
|
||||
for (byte i=0;i<bytecounter;i++){
|
||||
checksum=checksum + data[i];
|
||||
}
|
||||
checksum=checksum & 0x0f;
|
||||
if (checksum != (data[bytecounter])) return false; // all (excluding last) nibble added must result in last nibble value
|
||||
//==================================================================================
|
||||
// Prevent repeating signals from showing up, skips every second packet!
|
||||
//==================================================================================
|
||||
unsigned long tempval=(data[4])>>1;
|
||||
tempval=((tempval)<<16)+((data[3])<<8)+data[2];
|
||||
if( (SignalHash!=SignalHashPrevious) || (RepeatingTimer<millis()) || (SignalCRC != tempval) ){
|
||||
// not seen this RF packet recently
|
||||
SignalCRC=tempval;
|
||||
} else {
|
||||
return true; // already seen the RF packet recently, but still want the humidity
|
||||
}
|
||||
//==================================================================================
|
||||
// now process the various sensor types
|
||||
//==================================================================================
|
||||
// Output
|
||||
// ----------------------------------
|
||||
if (data[0] == 0x04) { // Meteo sensor
|
||||
sprintf(pbuffer, "20;%02X;", PKSequenceNumber++); // Node and packet number
|
||||
Serial.print( pbuffer );
|
||||
Serial.print(F("LaCrosseV3;ID=")); // Label
|
||||
PrintHex8( data,2);
|
||||
|
||||
sensor_data = data[4]*100;
|
||||
sensor_data = sensor_data + data[3]*10;
|
||||
sensor_data = sensor_data + data[2];
|
||||
sprintf(pbuffer, ";TEMP=%04x;", sensor_data);
|
||||
Serial.print( pbuffer );
|
||||
|
||||
sensor_data = data[7]*10;
|
||||
sensor_data = sensor_data + data[6];
|
||||
sprintf(pbuffer, "HUM=%04d;", sensor_data);
|
||||
Serial.print( pbuffer );
|
||||
|
||||
sensor_data = data[10]*100;
|
||||
sensor_data = sensor_data + data[9]*10;
|
||||
sensor_data = sensor_data + data[8];
|
||||
sensor_data = sensor_data + 200;
|
||||
sprintf(pbuffer, "BARO=%04x;", sensor_data);
|
||||
Serial.println( pbuffer );
|
||||
|
||||
RawSignal.Repeats=false;
|
||||
RawSignal.Number=0;
|
||||
success=true;
|
||||
} else
|
||||
if (data[0] == 0x02) { // Rain sensor
|
||||
sprintf(pbuffer, "20;%02X;", PKSequenceNumber++); // Node and packet number
|
||||
Serial.print( pbuffer );
|
||||
Serial.print(F("LaCrosseV3;ID=")); // Label
|
||||
PrintHex8( data,2);
|
||||
|
||||
sensor_data = data[4]*100;
|
||||
sensor_data = sensor_data + data[3]*10;
|
||||
sensor_data = sensor_data + data[2];
|
||||
sprintf(pbuffer, ";RAIN=%04x;", sensor_data);
|
||||
Serial.println( pbuffer );
|
||||
|
||||
RawSignal.Repeats=false;
|
||||
RawSignal.Number=0;
|
||||
success=true;
|
||||
} else
|
||||
if (data[0] == 0x03) { // wind sensor
|
||||
sprintf(pbuffer, "20;%02X;", PKSequenceNumber++); // Node and packet number
|
||||
Serial.print( pbuffer );
|
||||
Serial.print(F("LaCrosseV3;ID=")); // Label
|
||||
PrintHex8( data,2);
|
||||
|
||||
sensor_data = data[4]*100;
|
||||
sensor_data = sensor_data + data[3]*10;
|
||||
sensor_data = sensor_data + data[2];
|
||||
sprintf(pbuffer, ";WINSP=%04x;", sensor_data);
|
||||
Serial.print( pbuffer );
|
||||
|
||||
sensor_data = ((data[7])>>2)*100;
|
||||
sensor_data = sensor_data + data[6]*10;
|
||||
sensor_data = sensor_data + data[5];
|
||||
sensor_data = sensor_data / 22.5;
|
||||
sprintf(pbuffer, "WINDIR=%04x;", sensor_data);
|
||||
Serial.println( pbuffer );
|
||||
|
||||
RawSignal.Repeats=false;
|
||||
RawSignal.Number=0;
|
||||
success=true;
|
||||
} else
|
||||
if (data[0] == 0x05) { // UV sensor
|
||||
sprintf(pbuffer, "20;%02X;", PKSequenceNumber++); // Node and packet number
|
||||
Serial.print( pbuffer );
|
||||
Serial.print(F("LaCrosseV3;ID=")); // Label
|
||||
PrintHex8( data,2);
|
||||
|
||||
sensor_data = data[4]*100;
|
||||
sensor_data = sensor_data + data[3]*10;
|
||||
sensor_data = sensor_data + data[2];
|
||||
sprintf(pbuffer, ";UV=%04x;", sensor_data);
|
||||
Serial.println( pbuffer );
|
||||
|
||||
RawSignal.Repeats=false;
|
||||
RawSignal.Number=0;
|
||||
success=true;
|
||||
}
|
||||
//==================================================================================
|
||||
return success;
|
||||
}
|
||||
#endif // PLUGIN_041
|
|
@ -0,0 +1,293 @@
|
|||
//#######################################################################################################
|
||||
//## This Plugin is only for use with the RFLink software package ##
|
||||
//## Plugin-42 UPM/Esic ##
|
||||
//#######################################################################################################
|
||||
/*********************************************************************************************\
|
||||
* Dit protocol zorgt voor ontvangst van UPM/Esic weerstation buitensensoren
|
||||
* Tevens alle sensoren die het UPM/Esic (W.H. Mandolyn International Ltd) protocol volgen waaronder:
|
||||
* UPM, Esic, Emos, DVM, Clas Ohlson, Dickson
|
||||
* WT260,WT260H,WT440H,WT450,WT450H,WDS500,RG700
|
||||
*
|
||||
* Author : StuntTeam
|
||||
* 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!
|
||||
*********************************************************************************************
|
||||
* Changelog: v1.0 initial release
|
||||
*********************************************************************************************
|
||||
* Technical information:
|
||||
* Decodes signals from a UPM/Esic Weatherstation outdoor unit, (52/54 pulses, 36 bits, 433 MHz).
|
||||
* Supports two packet formats
|
||||
* --------------------------------------------------------------------------------------------
|
||||
* FORMAT 1:
|
||||
*
|
||||
* ____Byte 0_____ ____Byte 1_____ ____Byte 2_____ ____Byte 3_____ _Nib4__
|
||||
* 7 6 5 4 3 2 1 0 7 6 5 4 3 2 1 0 7 6 5 4 3 2 1 0 7 6 5 4 3 2 1 0 3 2 1 0
|
||||
* x x x x c c c c d d y y b S S S s s s s s P P P p p p p p p p p z z C C
|
||||
*
|
||||
* x = Constant, 1100, probably preamble
|
||||
* c = House Code (0 - 15)
|
||||
* d = Device Code (1 - 4) ?
|
||||
* y = ?
|
||||
* b = Low battery indication
|
||||
* S = Secondary value - Humidity/Wind direction (high bits)
|
||||
* s = Secondary value - Humidity/Wind direction (low bits)
|
||||
* P = Primary value - Temperature/Rain/Wind speed value (high bits)
|
||||
* p = Primary value - Temperature/Rain/Wind speed value (low bits)
|
||||
* z = Sequence number 0 - 2. Messages are sent in bursts of 3. For some senders this is always 0
|
||||
* C = Checksum. bit 1 is XOR of odd bits, bit 0 XOR of even bits in message
|
||||
*
|
||||
* If HouseCode = 10 and deviceCode = 2, then p and P is Wind speed
|
||||
* and h and H is Wind direction
|
||||
*
|
||||
* If HouseCode = 10 and deviceCode = 3, then p and P is rain
|
||||
*
|
||||
* Temp (C) = RawValue / 16 - 50
|
||||
* Rain (total mm) = RawValue * 0,7
|
||||
* Wind Speed (mph)= RawValue (* 1/3,6 for km/h)
|
||||
* Humidity (%) = RawValue / 2
|
||||
* Wind direction (deg) = RawValue * 22,5
|
||||
* --------------------------------------------------------------------------------------------
|
||||
* FORMAT 2:
|
||||
*
|
||||
* ____Byte 0_____ ____Byte 1_____ ____Byte 2_____ ____Byte 3_____ _Nib4__
|
||||
* 7 6 5 4 3 2 1 0 7 6 5 4 3 2 1 0 7 6 5 4 3 2 1 0 7 6 5 4 3 2 1 0 3 2 1 0
|
||||
* x x x x c c c c d d y y b h h h h h h h T T T T T T T T t t t t t t t p
|
||||
*
|
||||
* x = Constant, 1100, probably preamble
|
||||
* c = House Code (0 - 15)
|
||||
* d = Device (Channel) Code (1 - 4) ?
|
||||
* y = ?
|
||||
* b = ?
|
||||
* h = Humidity (7 bits) (0111011 = 59 %)
|
||||
* T = Temperature (8 bits) (see below)
|
||||
* t = Temperature (7 bits) (see below)
|
||||
* p = Parity (xor of all bits should give 0)
|
||||
*
|
||||
* The temperature is transmitted as (temp + 50.0) * 128, which equals (temp * 128) + 6400. Adding 50.0 °C makes
|
||||
* all values positive, an unsigned 15 bit integer where the first 8 bits correspond to the whole part of the temperature
|
||||
* (here 01001001, decimal 73, substract 50 = 23). Remaining 7 bits correspond to the fractional part.
|
||||
* Sample:
|
||||
* 20;64;DEBUG;Pulses=52;Pulses(uSec)=875,875,825,875,1725,1800,1725,1800,1725,850,825,1800,1725,875,800,850,825,1800,1725,1800,800,875,800,850,1725,1800,825,850,1725,850,825,1800,1725,1800,825,850,1725,875,800,1800,800,875,800,850,825,850,1725,1800,1750,1800,475;
|
||||
* 11000001 00110000 11100100 01100000 0010
|
||||
*
|
||||
*20;C3;DEBUG;Pulses=52;Pulses(uSec)=950,975,850,975,1850,1975,1875,1975,1850,975,850,1975,1850,975,850,975,850,2000,1850,975,875,975,850,975,850,2000,850,975,1850,2000,850,975,1850,2000,850,975,1875,975,850,975,850,975,850,2000,1850,1975,1850,2000,1850,1975,225;
|
||||
*20;C4;DEBUG;Pulses=52;Pulses(uSec)=950,975,850,975,1850,2000,1875,2000,1850,975,850,2000,1850,975,850,975,850,2000,1850,975,875,950,875,975,850,2000,850,975,1850,2000,850,975,1850,2000,850,975,1875,975,850,975,850,975,850,2000,1850,2000,1850,2000,1850,2000,225;
|
||||
*20;C5;DEBUG;Pulses=52;Pulses(uSec)=950,975,850,975,1850,2000,1875,2000,1850,975,850,2000,1850,975,850,975,850,2000,1850,975,875,975,850,975,850,1975,850,975,1850,1975,850,975,1850,2000,850,975,1875,975,850,975,850,975,850,2000,1850,2000,1850,2000,1850,2000,225;
|
||||
*20;32;DEBUG;Pulses=48;Pulses(uSec)=850,900,875,900,1850,1875,1850,1875,1850,900,875,1875,1850,900,875,900,875,1875,1850,900,875,1875,1850,1875,1825,900,875,1875,875,900,1850,1875,875,900,875,900,1850,1875,1825,1875,1850,1875,1850,1875,1825,1875,500;
|
||||
*20;33;UPM/Esic;ID=0001;TEMP=0104;HUM=33;BAT=OK;
|
||||
|
||||
925,900,875,900,1825,1875,1850,1875,1850,900,
|
||||
875,1875,1850,900,850,900,850,1875,1850,900,
|
||||
850,1875,1850,900,850,1875,1850,1875,875,900,
|
||||
1850,1875,875,900,875,900,1825,1875,1850,900,
|
||||
875,1875,1850,900,875,1875,850,900,875,900,
|
||||
500 51
|
||||
0011111011 0011010111 0110011101 10100
|
||||
\*********************************************************************************************/
|
||||
#define UPM_MIN_PULSECOUNT 46
|
||||
#define UPM_MAX_PULSECOUNT 56
|
||||
|
||||
#define UPM_PULSELOHI 1100/RAWSIGNAL_SAMPLE_RATE
|
||||
#define UPM_PULSEHIHI 2075/RAWSIGNAL_SAMPLE_RATE
|
||||
#define UPM_PULSEHILO 1600/RAWSIGNAL_SAMPLE_RATE
|
||||
|
||||
#ifdef PLUGIN_042
|
||||
boolean Plugin_042(byte function, char *string) {
|
||||
if (RawSignal.Number < UPM_MIN_PULSECOUNT || RawSignal.Number > UPM_MAX_PULSECOUNT) return false;
|
||||
|
||||
byte rc=0;
|
||||
unsigned long bitstream1=0L; // holds first 10 bits
|
||||
unsigned long bitstream2=0L; // holds last 26 bits
|
||||
|
||||
int temperature=0;
|
||||
int humidity=0;
|
||||
int rain=0;
|
||||
int winds=0;
|
||||
int windd=0;
|
||||
byte battery=0;
|
||||
byte units=0;
|
||||
byte devicecode=0;
|
||||
byte checksum=0;
|
||||
byte bitcounter=0; // counts number of received bits (converted from pulses)
|
||||
byte halfbit=0; // high pulse = 1, 2 low pulses = 0, halfbit keeps track of low pulses
|
||||
byte msgformat=0;
|
||||
//==================================================================================
|
||||
for(int x=1;x <RawSignal.Number;x++) { // get bytes
|
||||
if ((RawSignal.Pulses[x] > UPM_PULSEHILO) && (RawSignal.Pulses[x] < UPM_PULSEHIHI)) {
|
||||
if (halfbit==1) { // UPM cant receive a 1 bit after a single low value
|
||||
return false; // pulse error, must not be a UPM packet or reception error
|
||||
}
|
||||
if (bitcounter < 10) {
|
||||
bitstream1 = (bitstream1 << 1);
|
||||
bitcounter++; // only need to count the first 10 bits
|
||||
} else {
|
||||
bitstream2 = (bitstream2 << 1);
|
||||
bitcounter++; // only need to count the first 10 bits
|
||||
}
|
||||
halfbit=0; // wait for next first low or high pulse
|
||||
} else {
|
||||
if ((RawSignal.Pulses[x] > UPM_PULSELOHI) ) return false; // Not a valid UPM pulse length
|
||||
if (halfbit == 0) { // 2 times a low value = 0 bit
|
||||
halfbit=1; // first half received
|
||||
} else {
|
||||
if (bitcounter < 10) {
|
||||
bitstream1 = (bitstream1 << 1) | 0x1;
|
||||
bitcounter++; // only need to count the first 10 bits
|
||||
} else {
|
||||
bitstream2 = (bitstream2 << 1) | 0x1;
|
||||
bitcounter++; // only need to count the first 10 bits
|
||||
}
|
||||
halfbit=0; // wait for next first low or high pulse
|
||||
}
|
||||
}
|
||||
if (bitcounter > 36) return false; // too many bits, it cant be the right protocol
|
||||
}
|
||||
//==================================================================================
|
||||
if ( (bitstream1 >> 6 ) != 0x0c ) return false; // sanity check, first 4 bits should always be '1100' to be a valid UPM/Esic packet
|
||||
if ( bitstream1 == 0x00 ) return false; // sanity check
|
||||
if ( bitstream2 == 0x00 ) return false; // sanity check
|
||||
//==================================================================================
|
||||
for (byte i=0;i<9;i=i+2){ // perform a checksum check to make sure the packet is a valid UPM/Esic packet
|
||||
checksum=checksum ^ ((bitstream1 >> i) &3); // Checksum - xor all odd and all even bits should match the last two bits
|
||||
}
|
||||
for (byte i=2;i<25;i=i+2){
|
||||
checksum=checksum ^ ((bitstream2 >> i) &3);
|
||||
}
|
||||
if (checksum == (bitstream2 &3 )) { // did the format 1 checksum calculation match?
|
||||
msgformat=1; // Yes, set it
|
||||
} else { // else perform a bit parity check to see if we have format 2
|
||||
checksum=checksum ^ ((bitstream2) &3); // xor the last 2 bits
|
||||
units = (checksum >> 1) & 0x01; // get the odd bit of the checksum result
|
||||
checksum=(checksum & 0x01) ^ units; // xor the odd with the even bit of the checksum result
|
||||
if (checksum == 0) { // did the format 2 parity checksum calculation match?
|
||||
msgformat=2;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
//==================================================================================
|
||||
// Prevent repeating signals from showing up
|
||||
//==================================================================================
|
||||
if( (SignalHash!=SignalHashPrevious) || ((RepeatingTimer+1000<millis()) && (SignalCRC != bitstream1)) || (SignalCRC != bitstream1) ) {
|
||||
SignalCRC=bitstream1; // not seen the RF packet recently
|
||||
} else {
|
||||
return true; // already seen the RF packet recently
|
||||
}
|
||||
//==================================================================================
|
||||
// now process the various sensor types
|
||||
//==================================================================================
|
||||
units=bitstream1 & 0x03; // housecode format 1&2
|
||||
rc=units; // housecode format 1&2
|
||||
devicecode=(bitstream1 >> 2) & 0x0f; // devicecode format 1&2
|
||||
//==================================================================================
|
||||
if (msgformat==1) {
|
||||
battery = (bitstream2 >> 23) & 1; // battery state 1=low 0=ok
|
||||
if ((rc==10) && (devicecode==2)) { // wind
|
||||
units = (bitstream2 >> 4) & 0x0f;
|
||||
winds = (bitstream2 >> 8) & 0x7f;
|
||||
windd = (bitstream2 >> 15) & 0x0f; //0xff; // wind direction
|
||||
//==================================================================================
|
||||
// Output
|
||||
// ----------------------------------
|
||||
Serial.print("20;");
|
||||
PrintHexByte(PKSequenceNumber++);
|
||||
Serial.print(F(";UPM/Esic;ID=")); // Label
|
||||
PrintHexByte(rc);
|
||||
PrintHexByte(devicecode);
|
||||
// ----------------------------------
|
||||
sprintf(pbuffer, ";WINSP=%02x;", winds);
|
||||
Serial.print( pbuffer );
|
||||
sprintf(pbuffer, "WINDIR=%04d;", windd);
|
||||
Serial.print( pbuffer );
|
||||
if (battery==1) { // battery status
|
||||
Serial.print(F("BAT=LOW;"));
|
||||
} else {
|
||||
Serial.print(F("BAT=OK;"));
|
||||
}
|
||||
Serial.println();
|
||||
//==================================================================================
|
||||
} else
|
||||
if ((rc==10) && (devicecode==3)) { // rain
|
||||
units = (bitstream2 >> 4) & 0x0f;
|
||||
rain = (bitstream2 >> 8) & 0x7f;
|
||||
rain = rain * 7; // Serial.print( (float)rain * 0.7 );
|
||||
//==================================================================================
|
||||
// Output
|
||||
// ----------------------------------
|
||||
Serial.print("20;");
|
||||
PrintHexByte(PKSequenceNumber++);
|
||||
Serial.print(F(";UPM/Esic;ID=")); // Label
|
||||
PrintHexByte(rc);
|
||||
PrintHexByte(devicecode);
|
||||
// ----------------------------------
|
||||
sprintf(pbuffer, ";RAIN=%04x;", rain);
|
||||
Serial.print( pbuffer );
|
||||
if (battery==1) { // battery status
|
||||
Serial.print(F("BAT=LOW;"));
|
||||
} else {
|
||||
Serial.print(F("BAT=OK;"));
|
||||
}
|
||||
Serial.println();
|
||||
//==================================================================================
|
||||
} else { // temperature & Humidity
|
||||
units = (bitstream2 >> 4) & 0x0f; // temperature
|
||||
temperature = (bitstream2 >> 8) & 0x7f;
|
||||
temperature = temperature-50;
|
||||
temperature = (temperature*10) + units;
|
||||
if (temperature > 0x3e8) return false;
|
||||
humidity = (bitstream2 >> 15) & 0xff; // humidity
|
||||
humidity = humidity / 2;
|
||||
//if (humidity==0) return false; // dont accept Bad humidity status
|
||||
//if (temperature > 1000) return false; // dont accept bad temperature
|
||||
//==================================================================================
|
||||
// Output
|
||||
// ----------------------------------
|
||||
Serial.print("20;");
|
||||
PrintHexByte(PKSequenceNumber++);
|
||||
Serial.print(F(";UPM/Esic;ID=")); // Label
|
||||
PrintHexByte(rc);
|
||||
PrintHexByte(devicecode);
|
||||
// ----------------------------------
|
||||
sprintf(pbuffer,";TEMP=%04x;", temperature);
|
||||
Serial.print( pbuffer );
|
||||
sprintf(pbuffer,"HUM=%02d;", humidity); // Humidity 0x15 = 21% decimal
|
||||
Serial.print( pbuffer );
|
||||
if (battery==1) { // battery status
|
||||
Serial.print(F("BAT=LOW;"));
|
||||
} else {
|
||||
Serial.print(F("BAT=OK;"));
|
||||
}
|
||||
Serial.println();
|
||||
//==================================================================================
|
||||
}
|
||||
} else {
|
||||
units = (bitstream2 >> 1) & 0x7f; // temperature
|
||||
temperature = (bitstream2 >> 8) & 0xff;
|
||||
temperature = temperature-50;
|
||||
temperature = (temperature*100) + units;
|
||||
temperature = temperature/10;
|
||||
if (temperature > 0x3e8) return false;
|
||||
humidity = (bitstream2 >> 16) & 0x7f; // humidity
|
||||
//==================================================================================
|
||||
// Output
|
||||
// ----------------------------------
|
||||
Serial.print("20;");
|
||||
PrintHexByte(PKSequenceNumber++);
|
||||
Serial.print(F(";UPM/Esic F2;ID=")); // Label
|
||||
PrintHexByte(rc);
|
||||
PrintHexByte(devicecode);
|
||||
// ----------------------------------
|
||||
sprintf(pbuffer,";TEMP=%04x;", temperature);
|
||||
Serial.print( pbuffer );
|
||||
sprintf(pbuffer,"HUM=%02x;", humidity);
|
||||
Serial.print( pbuffer );
|
||||
Serial.println();
|
||||
//==================================================================================
|
||||
}
|
||||
//==================================================================================
|
||||
RawSignal.Repeats=true; // suppress repeats of the same RF packet
|
||||
RawSignal.Number=0;
|
||||
return true;
|
||||
}
|
||||
#endif // PLUGIN_042
|
|
@ -0,0 +1,211 @@
|
|||
//#######################################################################################################
|
||||
//## This Plugin is only for use with the RFLink software package ##
|
||||
//## Plugin-43 LaCrosse ##
|
||||
//#######################################################################################################
|
||||
/*********************************************************************************************\
|
||||
* This plugin takes care of decoding LaCrosse weatherstation outdoor sensors
|
||||
* It also works for all non LaCrosse sensors that follow this protocol.
|
||||
* Lacrosse TX3-TH Thermo/Humidity, Lacrosse TX4, Lacrosse TX4U
|
||||
* WS7000-15: Anemometer, WS7000-16: Rain precipitation, WS2500-19: Brightness Luxmeter, WS7000-20: Thermo/Humidity/Barometer
|
||||
* TFA 30.3125 (temperature + humidity), TFA 30.3120.90 (temperature)
|
||||
*
|
||||
* Author : StuntTeam
|
||||
* 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!
|
||||
*********************************************************************************************
|
||||
* Changelog: v1.0 initial release
|
||||
*********************************************************************************************
|
||||
* Technical information:
|
||||
* Decodes signals from a LaCrosse Weatherstation outdoor unit, (88 pulses, 44 bits, 433 MHz).
|
||||
* Partially based on http://www.f6fbb.org/domo/sensors/tx3_th.php
|
||||
*
|
||||
* Temperature sensor (TX3)
|
||||
* Each frame is 44 bits long. It is composed of:
|
||||
* • 2 blocks of four bits = 0A (start sequence)
|
||||
* • 8 blocks of four bits (data)
|
||||
* • 1 block of four bits (checksum)
|
||||
*
|
||||
* The active values of the frames are explained below:
|
||||
*
|
||||
* Example
|
||||
* 0000 1010 0000 0000 1110 0111 0011 0001 0111 0011 1101
|
||||
* aaaa aaaa bbbb cccc cccd eeee ffff gggg hhhh iiii jjjj
|
||||
* 0 A 0 0 7 0 7 3 1 7 3 D
|
||||
*
|
||||
* 000a0004070705030705
|
||||
* 20;d8;LaCrosse;ID=0401;TEMP=00fd;
|
||||
* 000a0e04070608000608
|
||||
* 20;d9;LaCrosse;ID=0403;HUM=68;
|
||||
*
|
||||
* • a = Start sequence (always 0000 1010)
|
||||
* • b = Packet type (0=Thermo E=hygro)
|
||||
* • c = Address of sensor (changes when inserting batteries)
|
||||
* • d = Parity bit (c+d+e bits sum is even)
|
||||
* • e-i = Measured values:
|
||||
* e = tens (x 10)
|
||||
* f = ones (x 1)
|
||||
* g = digits (x 0.1) (is zero in case of humidity)
|
||||
* h = copy of e value
|
||||
* i = copy of f value
|
||||
* • j = Checksum (Lower four bits of the sum of all words)
|
||||
*
|
||||
* Checksum: (0 + A + 0 + 0 + E + 7 + 3 + 1 + 7 + 3) and F = D D
|
||||
* Sample:
|
||||
* 20;11;DEBUG;Pulses=88;Pulses(uSec)=1200,875,1125,875,1125,875,1125,900,400,900,1150,875,400,900,1150,875,1125,875,1125,875,1150,875,1150,875,400,900,400,875,375,900,1150,875,1125,875,400,900,1150,875,1125,875,1125,875,400,900,400,875,1125,900,400,875,1150,875,1150,900,1125,875,1150,875,400,900,400,875,400,900,1150,875,400,900,400,875,1125,875,400,900,1150,900,1125,875,1150,875,375,900,400,900,400,900,400;
|
||||
* 20;9E;DEBUG;Pulses=88;Pulses(uSec)=1300,925,1225,925,1225,925,1200,925,425,925,1225,925,425,925,1225,925,1225,925,1225,925,1225,925,1225,925,1225,925,425,925,1225,925,1225,925,1225,925,425,925,425,925,1225,925,1225,925,425,925,425,925,425,925,1225,925,425,925,425,925,1225,925,425,925,1225,925,1225,925,1225,925,1225,925,425,925,425,925,425,925,1200,925,425,925,425,925,1225,925,1225,925,425,925,425,925,1225;
|
||||
* 20;9F;LaCrosse;ID=0403;TEMP=010c;
|
||||
* 20;A1;DEBUG;Pulses=88;Pulses(uSec)=1325,925,1225,925,1225,925,1225,925,425,925,1225,925,425,925,1225,925,425,925,425,925,425,925,1225,925,1225,925,425,925,1225,925,1225,925,1225,925,425,925,425,925,1225,925,1225,925,425,925,1225,925,425,925,1225,925,425,950,425,925,1225,925,1225,925,1225,925,1225,925,1225,925,1225,925,425,925,1225,925,425,925,1200,925,425,925,425,925,1225,925,425,925,1225,925,1225,925,1225;
|
||||
* 20;A2;LaCrosse;ID=0403;HUM=56;
|
||||
|
||||
* 1275,925,1225,925,1225,925,1200,925,425,925,1225,925,425,925,1225,900,1225,925,1200,925,1225,925,1225,925,1225,925,425,925,1225,925,1200,925,1225,925,425,925,425,900,1225,900,1225,925,425,925,425,925,425,925,1225,900,425,925,1225,925,1225,925,1225,925,425,950,1225,900,425,950,1225,925,425,925,425,900,425,950,1200,900,425,925,1225,925,1225,925,425,925,425,925,425,925,425
|
||||
|
||||
20;76;DEBUG;Pulses=88;Pulses(uSec)=810,1440,1200,930,1200,960,1200,930,390,930,1200,930,420,960,1200,930,1200,930,1200,930,1200,930,1200,930,1200,930,420,930,1200,960,1200,930,1200,930,420,930,420,930,1200,930,1200,960,390,930,420,930,420,960,1200,930,390,930,1200,930,420,930,1200,960,1170,930,1200,930,420,930,1200,930,420,930,420,930,420,930,1200,930,420,930,1200,930,420,930,420,930,420,930,1200,930,420,6990;
|
||||
0000 1010 0000 0100 0110 0111 0101 0001 0111 0101 1101
|
||||
20;78;DEBUG;Pulses=88;Pulses(uSec)=240,1980,1200,960,1200,960,1200,960,390,930,1200,930,390,960,1200,960,390,930,420,930,420,930,1200,930,1200,960,390,930,1200,930,1200,930,1200,930,420,930,420,930,1200,930,1200,930,420,930,420,930,1200,930,1200,930,420,960,1200,960,390,960,1200,930,1200,930,1200,930,1200,930,1200,930,420,960,390,930,1200,930,1200,960,390,930,1200,930,420,930,420,930,1200,930,1200,930,1200,6990;
|
||||
|
||||
0;29;DEBUG;Pulses=86;Pulses(uSec)=1260,930,1200,930,1200,930,420,960,1200,930,420,930,1200,930,1200,930,1200,930,1200,930,1200,930,1200,930,390,930,1200,960,1200,960,1200,930,420,930,390,960,1200,960,1200,930,420,930,420,930,390,960,1200,960,390,930,1200,930,1200,930,1200,930,420,930,420,960,1200,960,1200,930,390,960,390,960,390,930,1200,960,420,930,1200,930,1200,930,1200,930,1200,930,1200,930,1200,6990;
|
||||
20;2A;DEBUG;Pulses=50;Pulses(uSec)=1200,900,1140,870,390,900,360,900,390,900,1140,930,420,930,1200,930,1200,930,1200,930,420,930,390,960,1200,930,1200,930,390,930,420,960,390,930,1200,930,390,960,1200,960,1200,930,1200,960,1170,930,1200,930,1200,6990;
|
||||
20;2B;DEBUG;Pulses=86;Pulses(uSec)=1230,960,1200,960,1200,930,390,960,1200,930,420,930,1200,930,420,930,390,960,420,930,1200,930,1200,930,420,930,1200,960,1170,960,1200,930,390,930,420,930,390,930,1200,930,420,930,390,930,1200,960,1200,930,420,930,420,960,390,930,1200,930,1200,930,1200,930,1200,930,1200,930,390,960,390,930,1200,960,1200,930,420,930,420,960,390,930,420,960,390,930,1200,930,420,6990;
|
||||
|
||||
* --------------------------------------------------------------------------------------------
|
||||
* Rain Packet:
|
||||
* Each frame is 46 bits long. It is composed of:
|
||||
* 10bits of 0 (start sequence)
|
||||
* 7 blocks of four bits separated by a bit 1 to be checked and skipped
|
||||
*
|
||||
* The 1st bit of each word is LSB, so we have to reverse the 4 bits of each word.
|
||||
* Example
|
||||
* 0000 0000 0010 1111 1011 0010 1011 1111 1101
|
||||
* aaaa bbbb ccc1 ccc2 ccc3 dddd eeee
|
||||
* 2 F B 2 B F D
|
||||
*
|
||||
* a = sensor type (2=Rain meter)
|
||||
* b = sensor address
|
||||
* c = rain data (LSB thus the right order is c3 c2 c1)
|
||||
* d = Check Xor : (2 ^ F ^ B ^ 2 ^ B ^ F) = 0
|
||||
* e = Check Sum : (const5 + 2 + F + B + 2 + B + F) and F = D
|
||||
\*********************************************************************************************/
|
||||
#define LACROSSE43_PULSECOUNT 88
|
||||
#define LACROSSE43_PULSEMID 750/RAWSIGNAL_SAMPLE_RATE
|
||||
#define LACROSSE43_PULSEMAX 1350/RAWSIGNAL_SAMPLE_RATE
|
||||
#define LACROSSE43_PULSEMINMAX 550/RAWSIGNAL_SAMPLE_RATE
|
||||
|
||||
#define LACROSSE43_MIDLO 800/RAWSIGNAL_SAMPLE_RATE
|
||||
#define LACROSSE43_MIDHI 1000/RAWSIGNAL_SAMPLE_RATE
|
||||
|
||||
#ifdef PLUGIN_043
|
||||
boolean Plugin_043(byte function, char *string) {
|
||||
boolean success=false;
|
||||
if ( (RawSignal.Number < LACROSSE43_PULSECOUNT - 4) || (RawSignal.Number > LACROSSE43_PULSECOUNT + 4) ) return false;
|
||||
unsigned long bitstream1=0L; // holds first 16 bits
|
||||
unsigned long bitstream2=0L; // holds last 28 bits
|
||||
|
||||
int temperature=0;
|
||||
int humidity=0;
|
||||
byte checksum=0;
|
||||
byte bitcounter=0; // counts number of received bits (converted from pulses)
|
||||
byte data[10];
|
||||
//==================================================================================
|
||||
// get bytes
|
||||
for(int x=1;x<RawSignal.Number;x+=2) {
|
||||
if ((RawSignal.Pulses[x+1] < LACROSSE43_MIDLO) || (RawSignal.Pulses[x+1] > LACROSSE43_MIDHI)) {
|
||||
if (x < 2) { // Make sure the first bit is correct..
|
||||
RawSignal.Pulses[1]=1200/RAWSIGNAL_SAMPLE_RATE;
|
||||
} else {
|
||||
if (x+1 < RawSignal.Number) return false; // in between pulse check
|
||||
}
|
||||
}
|
||||
if (RawSignal.Pulses[x] > LACROSSE43_PULSEMID) {
|
||||
if (RawSignal.Pulses[x] > LACROSSE43_PULSEMAX) return false;
|
||||
if (bitcounter < 16) {
|
||||
bitstream1 = (bitstream1 << 1);
|
||||
bitcounter++; // only need to count the first 16 bits
|
||||
} else {
|
||||
bitstream2 = (bitstream2 << 1);
|
||||
}
|
||||
} else {
|
||||
if (RawSignal.Pulses[x] > LACROSSE43_PULSEMINMAX) return false;
|
||||
if (bitcounter < 16) {
|
||||
bitstream1 = (bitstream1 << 1) | 0x1;
|
||||
bitcounter++; // only need to count the first 16 bits
|
||||
} else {
|
||||
bitstream2 = (bitstream2 << 1) | 0x1;
|
||||
}
|
||||
}
|
||||
}
|
||||
//==================================================================================
|
||||
// all bytes received, make sure checksum is okay
|
||||
//==================================================================================
|
||||
if ((bitstream1 == 0) && (bitstream2 == 0)) return false;
|
||||
data[0] = (bitstream1 >> 12) & 0x0f; // prepare nibbles from bit stream
|
||||
if (data[0] != 0x00) return false;
|
||||
data[1] = (bitstream1 >> 8) & 0x0f;
|
||||
if (data[1] != 0x0a) return false;
|
||||
data[2] = (bitstream1 >> 4) & 0x0f;
|
||||
data[3] = (bitstream1 >> 0) & 0x0f;
|
||||
data[4] = (bitstream2 >> 24) & 0x0f;
|
||||
data[5] = (bitstream2 >> 20) & 0x0f;
|
||||
data[6] = (bitstream2 >> 16) & 0x0f;
|
||||
data[7] = (bitstream2 >> 12) & 0x0f;
|
||||
data[8] = (bitstream2 >> 8) & 0x0f;
|
||||
data[9] = (bitstream2 >> 4) & 0x0f;
|
||||
//==================================================================================
|
||||
// first perform a checksum check to make sure the packet is a valid LaCrosse packet
|
||||
for (byte i=0;i<10;i++){
|
||||
checksum=checksum + data[i];
|
||||
}
|
||||
checksum=checksum & 0x0f;
|
||||
if (checksum != (bitstream2 &0x0f )) return false;
|
||||
//==================================================================================
|
||||
// Prevent repeating signals from showing up, skips every second packet!
|
||||
//==================================================================================
|
||||
unsigned long tempval=(data[4])>>1;
|
||||
tempval=((tempval)<<16)+((data[3])<<8)+data[2];
|
||||
if( (SignalHash!=SignalHashPrevious) || (RepeatingTimer<millis()) || (SignalCRC != tempval) ){
|
||||
// not seen this RF packet recently
|
||||
SignalCRC=tempval;
|
||||
} else {
|
||||
return true; // already seen the RF packet recently, but still want the humidity
|
||||
}
|
||||
//==================================================================================
|
||||
// now process the various sensor types
|
||||
//==================================================================================
|
||||
// Output
|
||||
// ----------------------------------
|
||||
if (data[2] == 0x00) {
|
||||
temperature = data[5]*100;
|
||||
temperature = temperature + data[6]*10;
|
||||
temperature = temperature + data[7];
|
||||
temperature = temperature-500;
|
||||
data[4]=(data[4])>>1;
|
||||
|
||||
sprintf(pbuffer, "20;%02X;", PKSequenceNumber++); // Node and packet number
|
||||
Serial.print( pbuffer );
|
||||
Serial.print(F("LaCrosse;ID=")); // Label
|
||||
PrintHex8( data+3,2);
|
||||
sprintf(pbuffer, ";TEMP=%04x;", temperature);
|
||||
Serial.println( pbuffer );
|
||||
RawSignal.Repeats=false;
|
||||
RawSignal.Number=0;
|
||||
success=true;
|
||||
} else
|
||||
if (data[2] == 0x0e) {
|
||||
humidity=(data[5]*16)+data[6];
|
||||
if (humidity==0) return false; // humidity should not be 0
|
||||
data[4]=(data[4])>>1;
|
||||
|
||||
sprintf(pbuffer, "20;%02X;", PKSequenceNumber++); // Node and packet number
|
||||
Serial.print( pbuffer );
|
||||
Serial.print(F("LaCrosse;ID=")); // Label
|
||||
PrintHex8( data+3,2);
|
||||
sprintf(pbuffer, ";HUM=%02x;", (humidity)&0xff);
|
||||
Serial.println( pbuffer );
|
||||
RawSignal.Repeats=true;
|
||||
RawSignal.Number=0;
|
||||
success=true;
|
||||
}
|
||||
//==================================================================================
|
||||
return success;
|
||||
}
|
||||
#endif // PLUGIN_043
|
|
@ -0,0 +1,111 @@
|
|||
//#######################################################################################################
|
||||
//## This Plugin is only for use with the RFLink software package ##
|
||||
//## Plugin-44 Auriol V3 ##
|
||||
//#######################################################################################################
|
||||
/*********************************************************************************************\
|
||||
* This plugin takes care of decoding the Auriol protocol for sensor type Z32171A
|
||||
*
|
||||
* Author : StuntTeam
|
||||
* 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!
|
||||
*********************************************************************************************
|
||||
* Changelog: v1.0 initial release
|
||||
*********************************************************************************************
|
||||
* Technical Information:
|
||||
* Decodes signals from a Auriol Weatherstation outdoor unit, (40 bits, 433 MHz).
|
||||
*
|
||||
* Auriol Message Format:
|
||||
* 1011 1111 1001 1010 0110 0001 1011 0100 1001 0001
|
||||
* B F 9 A 6 1 B 4 9 1
|
||||
* AAAA AAAA BBBB CCDD EEEE EEEE EEEE FFFF FFFF GGHH
|
||||
*
|
||||
* A = ID?
|
||||
* B = Rolling code?
|
||||
* C = possibly battery indicator ?
|
||||
* D = trend (2 bits) indicating temp equal/up/down ?
|
||||
* E = Temperature => 0x61b (0x61b-0x4c4)=0x157 *5)=0x6b3 /9)=0xBE => 0xBE = 190 decimal!
|
||||
* F = humidity: 49%
|
||||
* G = ?
|
||||
* H = channel: 1 (2 bits)
|
||||
*
|
||||
* Sample:
|
||||
* 20;C2;DEBUG;Pulses=82;Pulses(uSec)=475,3850,450,1700,450,3825,450,3900,450,3725,450,3825,450,3825,450,3900,450,3725,450,1700,450,1700,450,3900,450,3725,450,1700,450,1700,450,1800,450,1625,450,3800,450,3825,450,1800,450,1625,450,1700,450,1700,450,1800,450,3725,450,3800,450,1700,450,1800,450,1625,450,3825,450,1700,450,3900,450,1625,450,1700,450,1700,450,3900,450,1625,450,1700,450,1700,450,3825,500;
|
||||
\*********************************************************************************************/
|
||||
#define AURIOLV3_PULSECOUNT 82
|
||||
|
||||
#ifdef PLUGIN_044
|
||||
boolean Plugin_044(byte function, char *string) {
|
||||
if (RawSignal.Number != AURIOLV3_PULSECOUNT) return false;
|
||||
unsigned long bitstream1=0L;
|
||||
unsigned long bitstream2=0L;
|
||||
byte rc=0;
|
||||
byte channel=0;
|
||||
byte bitcounter=0;
|
||||
unsigned long temperature=0;
|
||||
byte humidity=0;
|
||||
//==================================================================================
|
||||
// get all the bits we need (40 bits)
|
||||
for(int x=2;x < AURIOLV3_PULSECOUNT;x+=2) {
|
||||
if (RawSignal.Pulses[x+1]*RawSignal.Multiply > 650) return false;
|
||||
if (RawSignal.Pulses[x]*RawSignal.Multiply > 3500) {
|
||||
if (bitcounter < 16) {
|
||||
bitstream1 = (bitstream1 << 1) | 0x1;
|
||||
bitcounter++; // only need to count the first 10 bits
|
||||
} else {
|
||||
bitstream2 = (bitstream2 << 1) | 0x1;
|
||||
}
|
||||
} else {
|
||||
if (RawSignal.Pulses[x]*RawSignal.Multiply > 2000) return false;
|
||||
if (RawSignal.Pulses[x]*RawSignal.Multiply < 1500) return false;
|
||||
if (bitcounter < 16) {
|
||||
bitstream1 = (bitstream1 << 1);
|
||||
bitcounter++; // only need to count the first 10 bits
|
||||
} else {
|
||||
bitstream2 = (bitstream2 << 1);
|
||||
}
|
||||
}
|
||||
}
|
||||
//==================================================================================
|
||||
// Perform sanity checks and prevent repeating signals from showing up
|
||||
//==================================================================================
|
||||
if( (SignalHash!=SignalHashPrevious) || (RepeatingTimer<millis()) ) {
|
||||
if (bitstream1 == 0) return false; // not seen the RF packet recently
|
||||
if (bitstream2 == 0) return false;
|
||||
} else {
|
||||
return true; // already seen the RF packet recently
|
||||
}
|
||||
//==================================================================================
|
||||
rc = (bitstream1 >> 8) & 0xff ; // get rolling code
|
||||
temperature = ((bitstream2)>>12) & 0xfff; // get 12 temperature bits
|
||||
temperature = (temperature - 0x4c4) & 0xffff;
|
||||
temperature = (((temperature) * 5) / 9) & 0xffff;
|
||||
if (temperature > 3000) {
|
||||
temperature=4096-temperature; // fix for minus temperatures
|
||||
if (temperature > 0x258) return false; // temperature out of range ( > -60.0 degrees)
|
||||
temperature=temperature | 0x8000; // turn highest bit on for minus values
|
||||
} else {
|
||||
if (temperature > 0x258) return false; // temperature out of range ( > 60.0 degrees)
|
||||
}
|
||||
humidity = (bitstream2 >> 4) & 0xff ; // humidity
|
||||
channel=(bitstream2) & 0x03; // channel number
|
||||
//==================================================================================
|
||||
// Output
|
||||
// ----------------------------------
|
||||
Serial.print("20;");
|
||||
PrintHexByte(PKSequenceNumber++);
|
||||
Serial.print(F(";Auriol V3;ID=")); // Label
|
||||
PrintHexByte(rc);
|
||||
PrintHexByte(channel);
|
||||
// ----------------------------------
|
||||
sprintf(pbuffer, ";TEMP=%04x;", temperature); // temp
|
||||
Serial.print( pbuffer );
|
||||
sprintf(pbuffer, "HUM=%02x;", humidity); // hum
|
||||
Serial.print( pbuffer );
|
||||
Serial.println();
|
||||
//==================================================================================
|
||||
RawSignal.Repeats=true; // suppress repeats of the same RF packet
|
||||
RawSignal.Number=0;
|
||||
return true;
|
||||
}
|
||||
#endif // PLUGIN_044
|
|
@ -0,0 +1,105 @@
|
|||
//#######################################################################################################
|
||||
//## This Plugin is only for use with the RFLink software package ##
|
||||
//## Plugin-45 Auriol ##
|
||||
//#######################################################################################################
|
||||
/*********************************************************************************************\
|
||||
* This plugin takes care of decoding the Auriol protocol (Z31743) and other devices following the same protocol (Rubicson?)
|
||||
*
|
||||
* Author : StuntTeam
|
||||
* 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!
|
||||
*********************************************************************************************
|
||||
* Changelog: v1.0 initial release
|
||||
*********************************************************************************************
|
||||
* Technical Information:
|
||||
* Decodes signals from a Auriol Weatherstation outdoor unit, (32/36 bits, 433 MHz).
|
||||
* Auriol Message Format:
|
||||
* 1101 0110 1000 0000 1101 1111 1111 0000
|
||||
* AAAA AAAA BCCC DDDD DDDD DDDD EEEE FFFG
|
||||
*
|
||||
* A = Rolling Code, no change during normal operation. (Device 'Session' ID) (Might also be 4 bits RC and 4 bits for channel number)
|
||||
* B = Battery status, 1=OK, 0=LOW
|
||||
* C = Always 000
|
||||
* D = Temperature (21.5 degrees is shown as decimal value 215, minus values have the high bit set and need to be subtracted from a base value of 4096)
|
||||
* E = Unknown
|
||||
* F = Unknown
|
||||
* G = sum of all bits xored together
|
||||
*
|
||||
* Sample:
|
||||
* 20;34;DEBUG;Pulses=66;Pulses(uSec)=325,3725,325,1825,325,1825,325,1825,325,3700,325,3700,325,3700,325,3700,325,3700,325,1850,300,1825,325,1850,325,1825,325,1850,325,1825,300,1825,325,3725,300,3725,325,1825,325,1825,300,3725,300,1850,325,3725,300,1850,325,3725,300,3700,300,3725,300,1825,325,3700,325,3700,300,3700,325,1825,325;
|
||||
* 20;0A;DEBUG;Pulses=66;Pulses(uSec)=325,1850,300,1850,300,3700,300,1850,300,1850,300,1850,325,1850,300,1850,325,3700,325,1850,300,1850,300,1825,325,1850,300,1850,325,1825,300,1850,325,3725,300,3700,325,1825,300,1850,325,3700,300,3725,300,3725,300,1850,300,1850,300,3725,325,3700,300,1850,300,1825,325,1850,300,3700,300,1850,325;
|
||||
\*********************************************************************************************/
|
||||
#define AURIOL_PULSECOUNT 66
|
||||
|
||||
#ifdef PLUGIN_045
|
||||
boolean Plugin_045(byte function, char *string) {
|
||||
if (RawSignal.Number != AURIOL_PULSECOUNT) return false;
|
||||
unsigned long bitstream=0L;
|
||||
unsigned int temperature=0;
|
||||
byte rc=0;
|
||||
byte bat=0;
|
||||
byte checksumcalc=0;
|
||||
//==================================================================================
|
||||
if (RawSignal.Number == AURIOL_PULSECOUNT) {
|
||||
for(int x=2;x < AURIOL_PULSECOUNT;x+=2) {
|
||||
if (RawSignal.Pulses[x+1]*RawSignal.Multiply > 550) return false; // inbetween pulses should not exceed a length of 550
|
||||
if(RawSignal.Pulses[x]*RawSignal.Multiply > 3000) { // long bit = 1
|
||||
bitstream = (bitstream << 1) | 0x1;
|
||||
} else {
|
||||
if(RawSignal.Pulses[x]*RawSignal.Multiply < 1600) return false; // pulse length too short to be valid?
|
||||
if(RawSignal.Pulses[x]*RawSignal.Multiply > 2200) return false; // pulse length between 2000 - 3000 is invalid
|
||||
bitstream = (bitstream << 1); // short bit = 0
|
||||
}
|
||||
}
|
||||
}
|
||||
//==================================================================================
|
||||
// Prevent repeating signals from showing up
|
||||
//==================================================================================
|
||||
if( (SignalHash!=SignalHashPrevious) || (RepeatingTimer+1000<millis()) ) {
|
||||
// not seen the RF packet recently
|
||||
if (bitstream == 0) return false; // Perform a sanity check
|
||||
} else {
|
||||
// already seen the RF packet recently
|
||||
return true;
|
||||
}
|
||||
//==================================================================================
|
||||
for (int i=1;i<32;i++) { // Perform a checksum calculation to make sure the received packet is a valid Auriol packet
|
||||
checksumcalc=checksumcalc^ ((bitstream>>i)&0x01);
|
||||
}
|
||||
if (checksumcalc != (bitstream&0x01) ) return false;
|
||||
rc = (bitstream >> 20) & 0x07; // get 3 bits to perform another sanity check
|
||||
if (rc != 0) return false; // selected bits should always be 000
|
||||
//==================================================================================
|
||||
bat= (bitstream >> 23) & 0x01; // get battery strength indicator
|
||||
temperature = (bitstream >> 8) & 0xfff; // get 12 temperature bits
|
||||
rc = (bitstream >> 24) & 0xff; // get rolling code
|
||||
if (temperature > 3000) {
|
||||
temperature=4096-temperature; // fix for minus temperatures
|
||||
if (temperature > 0x258) return false; // temperature out of range ( > -60.0 degrees)
|
||||
temperature=temperature | 0x8000; // turn highest bit on for minus values
|
||||
} else {
|
||||
if (temperature > 0x258) return false; // temperature out of range ( > 60.0 degrees)
|
||||
}
|
||||
//==================================================================================
|
||||
// Output
|
||||
// ----------------------------------
|
||||
Serial.print("20;");
|
||||
PrintHexByte(PKSequenceNumber++);
|
||||
Serial.print(F(";Auriol;ID=00")); // Label
|
||||
PrintHexByte(rc);
|
||||
// ----------------------------------
|
||||
sprintf(pbuffer, ";TEMP=%04x;", temperature);
|
||||
Serial.print( pbuffer );
|
||||
if (bat==0) { // battery status
|
||||
Serial.print(F("BAT=LOW;"));
|
||||
} else {
|
||||
Serial.print(F("BAT=OK;"));
|
||||
}
|
||||
Serial.println();
|
||||
//==================================================================================
|
||||
RawSignal.Repeats=true; // suppress repeats of the same RF packet
|
||||
RawSignal.Number=0;
|
||||
return true;
|
||||
}
|
||||
#endif // PLUGIN_045
|
|
@ -0,0 +1,141 @@
|
|||
//#######################################################################################################
|
||||
//## This Plugin is only for use with the RFLink software package ##
|
||||
//## Plugin-46 Auriol / Xiron ##
|
||||
//#######################################################################################################
|
||||
/*********************************************************************************************\
|
||||
* This plugin takes care of decoding the Auriol protocol for sensor type Z31055A-TX and Xiron
|
||||
* Watshome YT6018-2 (From Fujian Youtong)
|
||||
*
|
||||
* Author : StuntTeam
|
||||
* 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!
|
||||
*********************************************************************************************
|
||||
* Changelog: v1.0 initial release
|
||||
*********************************************************************************************
|
||||
* Technical Information:
|
||||
* Decodes signals from a Auriol and Xiron Weatherstation outdoor unit, (36 bits, 433 MHz).
|
||||
*
|
||||
* Auriol Message Format:
|
||||
* 10100100 10 00 000011100110 1111 00000000 Temp = 23.60
|
||||
* AAAAAAAA BB CC DDDDDDDDDDDD EEEE FFFFFFFF
|
||||
* A = Rolling Code, no change during normal operation. (Device 'Session' ID) (Might also be 4 bits RC and 4 bits for channel number)
|
||||
* B = Battery status indicator on highest bit, 1=OK 0=LOW
|
||||
* C = Always 00 (Most likely channel number)
|
||||
* D = Temperature (12 bit, 21.5 degrees is shown as decimal value 215, minus values have the high bit set and need to be subtracted from a base value of 4096)
|
||||
* E = Always 1111 ?
|
||||
* F = Always 0000 0000 ?
|
||||
*
|
||||
* Xiron Message Format:
|
||||
* 01101110 10 00 000011101101 1111 00110011
|
||||
* AAAAAAAA BB CC DDDDDDDDDDDD EEEE FFFFFFFF
|
||||
* ID ?? Ch Temperature ? Humidity
|
||||
*
|
||||
* A = ID (Rolling Code, changes after battery replacement)
|
||||
* B = Battery status indicator on highest bit, 1=OK 0=LOW
|
||||
* C = Channel (1,2,3)
|
||||
* D = Temperature (12 bit, 21.5 degrees is shown as decimal value 215, minus values have the high bit set and need to be subtracted from a base value of 4096)
|
||||
* E = Always 1111 ?
|
||||
* F = Humidity
|
||||
*
|
||||
*
|
||||
* Sample:
|
||||
* 20;1F;DEBUG;Pulses=74;Pulses(uSec)=550,1575,525,675,525,1625,500,700,475,725,500,1675,500,700,500,725,475,1675,475,750,450,750,475,725,450,750,450,750,475,750,450,750,475,1675,450,1700,425,1700,450,750,450,750,450,1700,450,1700,450,775,450,1700,450,1700,450,1700,425,1700,425,775,450,775,450,775,425,775,425,775,425,775,450,775,425,775,425,
|
||||
\*********************************************************************************************/
|
||||
#define PLUGIN_ID 46
|
||||
#define AURIOLV2_PULSECOUNT 74
|
||||
|
||||
#ifdef PLUGIN_046
|
||||
boolean Plugin_046(byte function, char *string) {
|
||||
if (RawSignal.Number != AURIOLV2_PULSECOUNT) return false;
|
||||
unsigned long bitstream1=0L;
|
||||
unsigned long bitstream2=0L;
|
||||
byte rc=0;
|
||||
byte bat=0;
|
||||
int temperature=0;
|
||||
int humidity=0;
|
||||
byte channel=0;
|
||||
byte bitcounter=0;
|
||||
byte type=0;
|
||||
//==================================================================================
|
||||
// get all the bits we need (36 bits)
|
||||
for(int x=2;x < AURIOLV2_PULSECOUNT;x+=2) {
|
||||
if (RawSignal.Pulses[x+1]*RawSignal.Multiply > 700) return false;
|
||||
if (RawSignal.Pulses[x]*RawSignal.Multiply > 1400) {
|
||||
if (RawSignal.Pulses[x]*RawSignal.Multiply > 2100) return false;
|
||||
if (bitcounter < 24) {
|
||||
bitstream1 = (bitstream1 << 1) | 0x1;
|
||||
bitcounter++; // only need to count the first 10 bits
|
||||
} else {
|
||||
bitstream2 = (bitstream2 << 1) | 0x1;
|
||||
}
|
||||
} else {
|
||||
if (RawSignal.Pulses[x]*RawSignal.Multiply > 1100) return false;
|
||||
if (RawSignal.Pulses[x]*RawSignal.Multiply < 500) return false;
|
||||
if (bitcounter < 24) {
|
||||
bitstream1 = (bitstream1 << 1);
|
||||
bitcounter++; // only need to count the first 10 bits
|
||||
} else {
|
||||
bitstream2 = (bitstream2 << 1);
|
||||
}
|
||||
}
|
||||
}
|
||||
//==================================================================================
|
||||
if (bitstream1==0) return false; // Perform sanity check
|
||||
if ((bitstream2 & 0xF00) != 0xF00) return false; // check if 'E' has all 4 bits set
|
||||
if ((bitstream2 & 0xfff) != 0xF00) {
|
||||
type=1; // Xiron
|
||||
if (RawSignal.Pulses[0] != PLUGIN_ID) {
|
||||
return false; // only accept plugin_001 translated Xiron packets
|
||||
}
|
||||
} else {
|
||||
type=0; // Auriol
|
||||
rc = (bitstream1 >> 12) & 0x07; // get 3 bits
|
||||
if (rc != 0) return false; // should always be '000'
|
||||
}
|
||||
//==================================================================================
|
||||
bat= (bitstream1 >> 15) & 0x01; // get battery strength indicator
|
||||
rc = (bitstream1 >> 16) & 0xff; // get rolling code
|
||||
channel = ((bitstream1 >> 12) & 0x3)+1; // channel indicator
|
||||
temperature = (bitstream1) & 0xfff; // get 12 temperature bits
|
||||
if (temperature > 3000) {
|
||||
temperature=4096-temperature; // fix for minus temperatures
|
||||
if (temperature > 0x258) return false; // temperature out of range ( > -60.0 degrees)
|
||||
temperature=temperature | 0x8000; // turn highest bit on for minus values
|
||||
} else {
|
||||
if (temperature > 0x258) return false; // temperature out of range ( > 60.0 degrees)
|
||||
}
|
||||
if (type == 1) {
|
||||
humidity = (bitstream2) & 0xff ; // humidity
|
||||
}
|
||||
//==================================================================================
|
||||
// Output
|
||||
// ----------------------------------
|
||||
Serial.print("20;");
|
||||
PrintHexByte(PKSequenceNumber++);
|
||||
if (type == 0) {
|
||||
Serial.print(F(";Auriol V2;ID=")); // Label
|
||||
} else {
|
||||
Serial.print(F(";Xiron;ID=")); // Label
|
||||
}
|
||||
PrintHexByte(rc);
|
||||
PrintHexByte(channel);
|
||||
// ----------------------------------
|
||||
sprintf(pbuffer, ";TEMP=%04x;", temperature);
|
||||
Serial.print( pbuffer );
|
||||
if (type == 1) {
|
||||
sprintf(pbuffer, "HUM=%02d;", humidity);
|
||||
Serial.print( pbuffer );
|
||||
}
|
||||
if (bat==0) { // battery status
|
||||
Serial.print(F("BAT=LOW;"));
|
||||
} else {
|
||||
Serial.print(F("BAT=OK;"));
|
||||
}
|
||||
Serial.println();
|
||||
//==================================================================================
|
||||
RawSignal.Repeats=true; // suppress repeats of the same RF packet
|
||||
RawSignal.Number=0;
|
||||
return true;
|
||||
}
|
||||
#endif // PLUGIN_046
|
|
@ -0,0 +1,974 @@
|
|||
//#######################################################################################################
|
||||
//## This Plugin is only for use with the RFLink software package ##
|
||||
//## Plugin-48 Oregon V1/2/3 ##
|
||||
//#######################################################################################################
|
||||
/*********************************************************************************************\
|
||||
* This protocol takes care of receiving Oregon Scientific outdoor sensors that use the V1, V2 and V3 protocol
|
||||
*
|
||||
* models: THC238, THC268, THN132N, THWR288A, THRN122N, THN122N, AW129, AW131, THGR268, THGR122X,
|
||||
* THGN122N, THGN123N, THGR122NX, THGR228N, THGR238, WTGR800, THGR918, THGRN228NX, THGN500,
|
||||
* THGR810, RTGR328N, THGR328N, Huger BTHR918, BTHR918N, BTHR968, RGR126, RGR682, RGR918, PCR122
|
||||
* THWR800, THR128, THR138, THC138, OWL CM119, cent-a-meter, OWL CM113, Electrisave, RGR928
|
||||
* UVN128, UV138, UVN800, Huger-STR918, WGR918, WGR800, PCR800, WGTR800, RGR126, BTHG968
|
||||
*
|
||||
* Author : StuntTeam, Thibaut Girka
|
||||
* 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!
|
||||
*********************************************************************************************
|
||||
* Changelog: v0.1 beta
|
||||
*********************************************************************************************
|
||||
* Technical information:
|
||||
* Supports Oregon V1, V2 and V3 protocol messages
|
||||
* Core code from https://github.com/Cactusbone/ookDecoder/blob/master/ookDecoder.ino
|
||||
* Copyright (c) 2014 Charly Koza cactusbone@free.fr Copyright (c) 2012 Olivier Lebrun olivier.lebrun@connectingstuff.net
|
||||
* Copyright (c) 2012 Dominique Pierre (zzdomi) Copyright (c) 2010 Jean-Claude Wippler jcw@equi4.com
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation
|
||||
* files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy,
|
||||
* modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software
|
||||
* is furnished to do so, subject to the following conditions:
|
||||
* The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
|
||||
\*********************************************************************************************/
|
||||
#define OSV3_PULSECOUNT_MIN 50 // 126
|
||||
#define OSV3_PULSECOUNT_MAX 290 // make sure to check the max length in plugin 1 as well..!
|
||||
|
||||
#ifdef PLUGIN_048
|
||||
/*
|
||||
* Many devices use 160 bits, known exceptions:
|
||||
* 0xEA4c 136 bits // TH132N
|
||||
* 0xEA7c 240 bits // UV138
|
||||
* 0x5A5D / 1A99 176 bits // THGR918 / WTGR800
|
||||
* 0x5A6D 192 bits // BTHR918N
|
||||
* 0x8AEC 192 bits // RTGR328N
|
||||
* 0x9AEC 208 bits // RTGR328N
|
||||
* 0xDA78 144 bits // UVN800
|
||||
* 0x2A19 184 bits // RCR800
|
||||
* 0x2A1d 168 bits // WGR918
|
||||
*/
|
||||
// =====================================================================================================
|
||||
class DecodeOOK {
|
||||
protected:
|
||||
byte total_bits, bits, flip, state, pos, data[25];
|
||||
virtual char decode(word width) = 0;
|
||||
public:
|
||||
enum { UNKNOWN, T0, T1, T2, T3, OK, DONE };
|
||||
// -------------------------------------
|
||||
DecodeOOK() { resetDecoder(); }
|
||||
// -------------------------------------
|
||||
bool nextPulse(word width) {
|
||||
if (state != DONE)
|
||||
|
||||
switch (decode(width)) {
|
||||
case -1: resetDecoder(); break;
|
||||
case 1: done(); break;
|
||||
}
|
||||
return isDone();
|
||||
}
|
||||
// -------------------------------------
|
||||
bool isDone() const { return state == DONE; }
|
||||
// -------------------------------------
|
||||
const byte* getData(byte& count) const {
|
||||
count = pos;
|
||||
return data;
|
||||
}
|
||||
// -------------------------------------
|
||||
void resetDecoder() {
|
||||
total_bits = bits = pos = flip = 0;
|
||||
state = UNKNOWN;
|
||||
}
|
||||
// -------------------------------------
|
||||
// add one bit to the packet data buffer
|
||||
// -------------------------------------
|
||||
virtual void gotBit(char value) {
|
||||
total_bits++;
|
||||
byte *ptr = data + pos;
|
||||
*ptr = (*ptr >> 1) | (value << 7);
|
||||
|
||||
if (++bits >= 8) {
|
||||
bits = 0;
|
||||
if (++pos >= sizeof data) {
|
||||
resetDecoder();
|
||||
return;
|
||||
}
|
||||
}
|
||||
state = OK;
|
||||
}
|
||||
// -------------------------------------
|
||||
// store a bit using Manchester encoding
|
||||
// -------------------------------------
|
||||
void manchester(char value) {
|
||||
flip ^= value; // manchester code, long pulse flips the bit
|
||||
gotBit(flip);
|
||||
}
|
||||
// -------------------------------------
|
||||
// move bits to the front so that all the bits are aligned to the end
|
||||
// -------------------------------------
|
||||
void alignTail(byte max = 0) {
|
||||
// align bits
|
||||
if (bits != 0) {
|
||||
data[pos] >>= 8 - bits;
|
||||
for (byte i = 0; i < pos; ++i)
|
||||
data[i] = (data[i] >> bits) | (data[i + 1] << (8 - bits));
|
||||
bits = 0;
|
||||
}
|
||||
// optionally shift bytes down if there are too many of 'em
|
||||
if (max > 0 && pos > max) {
|
||||
byte n = pos - max;
|
||||
pos = max;
|
||||
for (byte i = 0; i < pos; ++i)
|
||||
data[i] = data[i + n];
|
||||
}
|
||||
}
|
||||
// -------------------------------------
|
||||
void reverseBits() {
|
||||
for (byte i = 0; i < pos; ++i) {
|
||||
byte b = data[i];
|
||||
for (byte j = 0; j < 8; ++j) {
|
||||
data[i] = (data[i] << 1) | (b & 1);
|
||||
b >>= 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
// -------------------------------------
|
||||
void reverseNibbles() {
|
||||
for (byte i = 0; i < pos; ++i)
|
||||
data[i] = (data[i] << 4) | (data[i] >> 4);
|
||||
}
|
||||
// -------------------------------------
|
||||
void done() {
|
||||
while (bits)
|
||||
gotBit(0); // padding
|
||||
state = DONE;
|
||||
}
|
||||
};
|
||||
|
||||
/*
|
||||
class OregonDecoderV1_org : public DecodeOOK {
|
||||
public:
|
||||
OregonDecoderV1_org() {}
|
||||
virtual char decode(word width) {
|
||||
if (200 <= width && width < 1200) {
|
||||
byte w = width >= 700;
|
||||
switch (state) {
|
||||
case UNKNOWN:
|
||||
if (w == 0)
|
||||
++flip;
|
||||
else if (10 <= flip && flip <= 50) {
|
||||
flip = 1;
|
||||
manchester(1);
|
||||
}
|
||||
else
|
||||
return -1;
|
||||
break;
|
||||
case OK:
|
||||
if (w == 0)
|
||||
state = T0;
|
||||
else
|
||||
manchester(1);
|
||||
break;
|
||||
case T0:
|
||||
if (w == 0)
|
||||
manchester(0);
|
||||
else
|
||||
return -1;
|
||||
break;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
if (width >= 2500 && pos >= 9)
|
||||
return 1;
|
||||
return -1;
|
||||
}
|
||||
};
|
||||
*/
|
||||
class OregonDecoderV1 : public DecodeOOK {
|
||||
public:
|
||||
OregonDecoderV1() {}
|
||||
virtual char decode(word width) {
|
||||
if (900 <= width && width < 3400) {
|
||||
byte w = width >= 2000;
|
||||
switch (state) {
|
||||
case UNKNOWN: // Detect preamble
|
||||
if (w == 0)
|
||||
++flip;
|
||||
else
|
||||
return -1;
|
||||
break;
|
||||
case OK:
|
||||
if (w == 0)
|
||||
state = T0;
|
||||
else
|
||||
manchester(1);
|
||||
break;
|
||||
case T0:
|
||||
if (w == 0)
|
||||
manchester(0);
|
||||
else
|
||||
return -1;
|
||||
break;
|
||||
default: // Unexpected state
|
||||
return -1;
|
||||
}
|
||||
return (pos == 4) ? 1 : 0; // Messages are fixed-size
|
||||
}
|
||||
if (width >= 3400) {
|
||||
if (flip < 10 || flip > 50)
|
||||
return -1; // No preamble
|
||||
switch (state) {
|
||||
case UNKNOWN:
|
||||
// First sync pulse, lowering edge
|
||||
state = T1;
|
||||
break;
|
||||
case T1:
|
||||
// Second sync pulse, lowering edge
|
||||
state = T2;
|
||||
break;
|
||||
case T2:
|
||||
// Last sync pulse, determines the first bit!
|
||||
if (width <= 5900) {
|
||||
state = T0;
|
||||
flip = 1;
|
||||
} else {
|
||||
state = OK;
|
||||
flip = 0;
|
||||
manchester(0);
|
||||
}
|
||||
break;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
};
|
||||
|
||||
class OregonDecoderV2 : public DecodeOOK {
|
||||
public:
|
||||
OregonDecoderV2() {}
|
||||
|
||||
// -------------------------------------
|
||||
// add one bit to the packet data buffer
|
||||
// -------------------------------------
|
||||
virtual void gotBit(char value) {
|
||||
if (!(total_bits & 0x01))
|
||||
{
|
||||
data[pos] = (data[pos] >> 1) | (value ? 0x80 : 00);
|
||||
}
|
||||
total_bits++;
|
||||
pos = total_bits >> 4;
|
||||
if (pos >= sizeof data) {
|
||||
resetDecoder();
|
||||
return;
|
||||
}
|
||||
state = OK;
|
||||
}
|
||||
// -------------------------------------
|
||||
virtual char decode(word width) {
|
||||
//if (200 <= width && width < 1200) {
|
||||
// byte w = width >= 675;
|
||||
if (150 <= width && width < 1200) {
|
||||
byte w = width >= 600;
|
||||
switch (state) {
|
||||
case UNKNOWN:
|
||||
if (w != 0) {
|
||||
// Long pulse
|
||||
++flip;
|
||||
}
|
||||
else if (w == 0 && 24 <= flip) {
|
||||
// Short pulse, start bit
|
||||
flip = 0;
|
||||
state = T0;
|
||||
}
|
||||
else {
|
||||
// Reset decoder
|
||||
return -1;
|
||||
}
|
||||
break;
|
||||
case OK:
|
||||
if (w == 0) {
|
||||
// Short pulse
|
||||
state = T0;
|
||||
}
|
||||
else {
|
||||
// Long pulse
|
||||
manchester(1);
|
||||
}
|
||||
break;
|
||||
case T0:
|
||||
if (w == 0) {
|
||||
// Second short pulse
|
||||
manchester(0);
|
||||
}
|
||||
else {
|
||||
// Reset decoder
|
||||
return -1;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
else if (width >= 2500 && pos >= 8) {
|
||||
return 1;
|
||||
}
|
||||
else {
|
||||
return -1;
|
||||
}
|
||||
return total_bits == 160 ? 1 : 0;
|
||||
}
|
||||
};
|
||||
|
||||
class OregonDecoderV3 : public DecodeOOK {
|
||||
public:
|
||||
OregonDecoderV3() {}
|
||||
// -------------------------------------
|
||||
// add one bit to the packet data buffer
|
||||
// -------------------------------------
|
||||
virtual void gotBit(char value) {
|
||||
data[pos] = (data[pos] >> 1) | (value ? 0x80 : 00);
|
||||
total_bits++;
|
||||
pos = total_bits >> 3;
|
||||
if (pos >= sizeof data) {
|
||||
resetDecoder();
|
||||
return;
|
||||
}
|
||||
state = OK;
|
||||
}
|
||||
// -------------------------------------
|
||||
virtual char decode(word width) {
|
||||
if (200 <= width && width < 1200) {
|
||||
byte w = width >= 675;
|
||||
switch (state) {
|
||||
case UNKNOWN:
|
||||
if (w == 0)
|
||||
++flip;
|
||||
else if (32 <= flip) {
|
||||
flip = 1;
|
||||
manchester(1);
|
||||
}
|
||||
else
|
||||
return -1;
|
||||
break;
|
||||
case OK:
|
||||
if (w == 0)
|
||||
state = T0;
|
||||
else
|
||||
manchester(1);
|
||||
break;
|
||||
case T0:
|
||||
if (w == 0)
|
||||
manchester(0);
|
||||
else
|
||||
return -1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
else {
|
||||
return -1;
|
||||
}
|
||||
return total_bits == 80 ? 1 : 0;
|
||||
}
|
||||
};
|
||||
|
||||
OregonDecoderV1 orscV1;
|
||||
OregonDecoderV2 orscV2;
|
||||
OregonDecoderV3 orscV3;
|
||||
|
||||
volatile word pulse;
|
||||
// =====================================================================================================
|
||||
// =====================================================================================================
|
||||
byte osdata[13];
|
||||
|
||||
void reportSerial(class DecodeOOK& decoder) {
|
||||
byte pos;
|
||||
const byte* data = decoder.getData(pos);
|
||||
for (byte i = 0; i < pos; ++i) {
|
||||
if (i < 13) osdata[i]=data[i];
|
||||
}
|
||||
decoder.resetDecoder();
|
||||
}
|
||||
// =====================================================================================================
|
||||
// calculate a packet checksum by performing a
|
||||
byte checksum(byte type, int count, byte check) {
|
||||
byte calc=0;
|
||||
// type 1, add all nibbles, deduct 10
|
||||
if (type == 1) {
|
||||
for(byte i = 0; i<count;i++) {
|
||||
calc += (osdata[i]&0xF0) >> 4;
|
||||
calc += (osdata[i]&0xF);
|
||||
}
|
||||
calc=calc-10;
|
||||
} else
|
||||
// type 2, add all nibbles up to count, add the 13th nibble , deduct 10
|
||||
if (type == 2) {
|
||||
for(byte i = 0; i<count;i++) {
|
||||
calc += (osdata[i]&0xF0) >> 4;
|
||||
calc += (osdata[i]&0xF);
|
||||
}
|
||||
calc += (osdata[6]&0xF);
|
||||
calc=calc-10;
|
||||
} else
|
||||
// type 3, add all nibbles up to count, subtract 10 only use the low 4 bits for the compare
|
||||
if (type == 3) {
|
||||
for(byte i = 0; i<count;i++) {
|
||||
calc += (osdata[i]&0xF0) >> 4;
|
||||
calc += (osdata[i]&0xF);
|
||||
}
|
||||
calc=calc-10;
|
||||
calc=(calc&0x0f);
|
||||
} else
|
||||
if (type == 4) {
|
||||
for(byte i = 0; i<count;i++) {
|
||||
calc += (osdata[i]&0xF0) >> 4;
|
||||
calc += (osdata[i]&0xF);
|
||||
}
|
||||
calc=calc-10;
|
||||
|
||||
}
|
||||
if (check == calc ) return 0;
|
||||
return 1;
|
||||
}
|
||||
// =====================================================================================================
|
||||
boolean Plugin_048(byte function, char *string) {
|
||||
if ((RawSignal.Number < OSV3_PULSECOUNT_MIN) || (RawSignal.Number > OSV3_PULSECOUNT_MAX) ) return false;
|
||||
|
||||
byte rc=0;
|
||||
byte found = 0;
|
||||
|
||||
int temp = 0;
|
||||
byte hum = 0;
|
||||
int comfort = 0;
|
||||
int baro = 0;
|
||||
int forecast = 0;
|
||||
int uv = 0;
|
||||
int wdir = 0;
|
||||
int wspeed = 0;
|
||||
int awspeed = 0;
|
||||
int rain = 0;
|
||||
int raintot = 0;
|
||||
|
||||
word p = pulse;
|
||||
// ==================================================================================
|
||||
for (int x = 1; x < RawSignal.Number; x++) {
|
||||
//for (int x = 0; x < RawSignal.Number; x++) {
|
||||
p = RawSignal.Pulses[x]*RawSignal.Multiply;
|
||||
if (p != 0) {
|
||||
if (orscV1.nextPulse(p)) {
|
||||
reportSerial(orscV1);
|
||||
found=1;
|
||||
}
|
||||
if (orscV2.nextPulse(p)) {
|
||||
reportSerial(orscV2);
|
||||
found=2;
|
||||
}
|
||||
if (orscV3.nextPulse(p)) {
|
||||
reportSerial(orscV3);
|
||||
found=3;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (found == 0) return false;
|
||||
|
||||
// ==================================================================================
|
||||
// Protocol and device info:
|
||||
// ==================================================================================
|
||||
//Serial.print("Oregon V");
|
||||
//Serial.print(found);
|
||||
//Serial.print(": ");
|
||||
//for(byte x=0; x<13;x++) {
|
||||
// Serial.print( osdata[x],HEX );
|
||||
// Serial.print((" "));
|
||||
//}
|
||||
//Serial.println();
|
||||
//Serial.print("Oregon ID=");
|
||||
unsigned int id=(osdata[0]<<8)+ (osdata[1]);
|
||||
rc=osdata[0];
|
||||
//Serial.println(id,HEX);
|
||||
// ==================================================================================
|
||||
// Process the various device types:
|
||||
// ==================================================================================
|
||||
// Oregon V1 packet structure
|
||||
// SL-109H, AcuRite 09955
|
||||
// TEMP + CRC
|
||||
// ==================================================================================
|
||||
// 8487101C
|
||||
// 84+87+10=11B > 1B+1 = 1C
|
||||
if (found==1) { // OSV1
|
||||
int sum = osdata[0]+osdata[1]+osdata[2]; // max. value is 0x2FD
|
||||
sum= (sum &0xff) + (sum>>8); // add overflow to low byte
|
||||
if (osdata[3] != (sum & 0xff) ) {
|
||||
//Serial.println("CRC Error");
|
||||
return false;
|
||||
}
|
||||
// -------------
|
||||
//temp = ((osdata[2]>>4) * 100) + ((osdata[1] & 0x0F) * 10) + ((osdata[1] >> 4));
|
||||
//if ((osdata[2] & 0x02) == 2) temp=temp | 0x8000; // bit 1 set when temp is negative, set highest bit on temp valua
|
||||
temp = ((osdata[2] & 0x0F) * 100) + ((osdata[1] >> 4) * 10) + ((osdata[1] & 0x0F));
|
||||
if ((osdata[2] & 0x20) == 0x20) temp=temp | 0x8000; // bit 1 set when temp is negative, set highest bit on temp valua
|
||||
// ----------------------------------
|
||||
// Output
|
||||
// ----------------------------------
|
||||
Serial.print("20;");
|
||||
PrintHexByte(PKSequenceNumber++);
|
||||
Serial.print(F(";OregonV1;ID=00")); // Label
|
||||
//sprintf(pbuffer, "ID=00%02x;", rc & 0xCF);
|
||||
PrintHexByte((rc)&0xcf); // rolling code + channel
|
||||
// ----------------------------------
|
||||
sprintf(pbuffer, ";TEMP=%04x;", temp);
|
||||
Serial.print( pbuffer );
|
||||
if (osdata[2] & 0x80) {
|
||||
Serial.print(F("BAT=LOW;"));
|
||||
} else {
|
||||
Serial.print(F("BAT=OK;"));
|
||||
}
|
||||
Serial.println();
|
||||
}
|
||||
// ==================================================================================
|
||||
// ea4c Outside (Water) Temperature: THC238, THC268, THN132N, THWR288A, THRN122N, THN122N, AW129, AW131
|
||||
// TEMP + BAT + CRC
|
||||
// ca48 Pool (Water) Temperature: THWR800
|
||||
// 0a4d Indoor Temperature: THR128, THR138, THC138
|
||||
// ==================================================================================
|
||||
// OSV2 EA4C20725C21D083 // THN132N
|
||||
// OSV2 EA4C101360193023 // THN132N
|
||||
// OSV2 EA4C40F85C21D0D4 // THN132N
|
||||
// OSV2 EA4C20809822D013
|
||||
// 0123456789012345
|
||||
// 0 1 2 3 4 5 6 7
|
||||
if(id == 0xea4c || id == 0xca48 || id == 0x0a4d) {
|
||||
byte sum=(osdata[7]&0x0f) <<4;
|
||||
sum=sum+(osdata[6]>>4);
|
||||
if ( checksum(2,6, sum) !=0) { // checksum = all nibbles 0-11+13 results is nibbles 15 <<4 + 12
|
||||
//Serial.println("CRC Error");
|
||||
return false;
|
||||
}
|
||||
// -------------
|
||||
temp = ((osdata[5]>>4) * 100) + ((osdata[5] & 0x0F) * 10) + ((osdata[4] >> 4));
|
||||
if ((osdata[6] & 0x0F) >= 8) temp=temp | 0x8000;
|
||||
// ----------------------------------
|
||||
// Output
|
||||
// ----------------------------------
|
||||
Serial.print("20;");
|
||||
PrintHexByte(PKSequenceNumber++);
|
||||
Serial.print(F(";Oregon Temp;ID=")); // Label
|
||||
//PrintHexByte(rc);
|
||||
PrintHexByte(osdata[3]);
|
||||
PrintHexByte(osdata[2]);
|
||||
// ----------------------------------
|
||||
sprintf(pbuffer, ";TEMP=%04x;", temp);
|
||||
Serial.print( pbuffer );
|
||||
//if ((osdata[3] & 0x0F) >= 4) {
|
||||
if ((osdata[4] & 0x0c) >= 4) {
|
||||
Serial.print(F("BAT=LOW;"));
|
||||
} else {
|
||||
Serial.print(F("BAT=OK;"));
|
||||
}
|
||||
Serial.println();
|
||||
} else
|
||||
// ==================================================================================
|
||||
// 1a2d Indoor Temp/Hygro: THGN122N, THGN123N, THGR122NX, THGR228N, THGR238, THGR268, THGR122X
|
||||
// 1a3d Outside Temp/Hygro: THGR918, THGRN228NX, THGN500
|
||||
// fa28 Indoor Temp/Hygro: THGR810
|
||||
// *aac Outside Temp/Hygro: RTGR328N
|
||||
// ca2c Outside Temp/Hygro: THGR328N
|
||||
// fab8 Outside Temp/Hygro: WTGR800
|
||||
// TEMP + HUM sensor + BAT + CRC
|
||||
// ==================================================================================
|
||||
// OSV2 AACC13783419008250AD[RTGR328N,...] Id:78 ,Channel:0 ,temp:19.30 ,hum:20 ,bat:10
|
||||
// OSV2 1A2D40C4512170463EE6[THGR228N,...] Id:C4 ,Channel:3 ,temp:21.50 ,hum:67 ,bat:90
|
||||
// OSV2 1A2D1072512080E73F2C[THGR228N,...] Id:72 ,Channel:1 ,temp:20.50 ,hum:78 ,bat:90
|
||||
// OSV2 1A2D103742197005378E // THGR228N
|
||||
// OSV3 FA28A428202290834B46 //
|
||||
// OSV3 FA2814A93022304443BE // THGR810
|
||||
// OSV2 1A2D1002 02060552A4C
|
||||
// 1A3D10D91C273083..
|
||||
// 1A3D10D90C284083..
|
||||
// 01234567890123456789
|
||||
// 0 1 2 3 4 5
|
||||
// F+A+2+8+1+4+A+9+3+0+2+2+3+0+4+4=4d-a=43
|
||||
if(id == 0xfa28 || id == 0x1a2d || id == 0x1a3d || (id&0xfff)==0xACC || id == 0xca2c || id == 0xfab8 ) {
|
||||
if ( checksum(1,8,osdata[8]) !=0) return false; // checksum = all nibbles 0-15 results is nibbles 16.17
|
||||
// -------------
|
||||
temp = ((osdata[5]>>4) * 100) + ((osdata[5] & 0x0F) * 10) + ((osdata[4] >> 4));
|
||||
if ((osdata[6] & 0x0F) >= 8) temp=temp | 0x8000;
|
||||
// -------------
|
||||
hum = ((osdata[7] & 0x0F)*16)+ (osdata[6] >> 4);
|
||||
// ----------------------------------
|
||||
// Output
|
||||
// ----------------------------------
|
||||
Serial.print("20;");
|
||||
PrintHexByte(PKSequenceNumber++);
|
||||
Serial.print(F(";Oregon TempHygro;ID=")); // Label
|
||||
PrintHexByte(osdata[1]);
|
||||
PrintHexByte(osdata[3]);
|
||||
// ----------------------------------
|
||||
sprintf(pbuffer, ";TEMP=%04x;", temp);
|
||||
Serial.print( pbuffer );
|
||||
sprintf(pbuffer, "HUM=%02x;", hum);
|
||||
Serial.print( pbuffer );
|
||||
if ((osdata[4] & 0x0F) >= 4) {
|
||||
Serial.print(F("BAT=LOW;"));
|
||||
} else {
|
||||
Serial.print(F("BAT=OK;"));
|
||||
}
|
||||
Serial.println();
|
||||
} else
|
||||
// ==================================================================================
|
||||
// 5a5d Indoor Temp/Hygro/Baro: Huger - BTHR918
|
||||
// 5a6d Indoor Temp/Hygro/Baro: BTHR918N, BTHR968. BTHG968
|
||||
// TEMP + HUM + BARO + FORECAST + BAT
|
||||
// NO CRC YET
|
||||
// ==================================================================================
|
||||
// 5A 6D 00 7A 10 23 30 83 86 31
|
||||
// 5+a+6+d+7+a+1+2+3+3+8+3=47 -a=3d +8=4f +8+6=55
|
||||
// 5+a+6+d+7+a+1+2+3+3=3c-a=32
|
||||
// 5+a+6+d+7+a+1+2+3+3+0+8+3+8+6=55 -a =4b +3=4e !=1
|
||||
// 0 1 2 3 4 5 6 7 8 9
|
||||
if(id == 0x5a6d || id == 0x5a5d || id == 0x5d60) {
|
||||
// -------------
|
||||
temp = ((osdata[5]>>4) * 100) + ((osdata[5] & 0x0F) * 10) + ((osdata[4] >> 4));
|
||||
if ((osdata[6] & 0x0F) >= 8) temp=temp | 0x8000;
|
||||
// -------------
|
||||
hum = ((osdata[7] & 0x0F)*10)+ (osdata[6] >> 4);
|
||||
|
||||
//0: normal, 4: comfortable, 8: dry, C: wet
|
||||
int tmp_comfort = osdata[7] >> 4;
|
||||
if (tmp_comfort == 0x00)
|
||||
comfort=0;
|
||||
else if (tmp_comfort == 0x04)
|
||||
comfort=1;
|
||||
else if (tmp_comfort == 0x08)
|
||||
comfort=2;
|
||||
else if (tmp_comfort == 0x0C)
|
||||
comfort=3;
|
||||
|
||||
// -------------
|
||||
baro = (osdata[8] + 856); // max value = 1111 / 0x457
|
||||
|
||||
//2: cloudy, 3: rainy, 6: partly cloudy, C: sunny
|
||||
int tmp_forecast = osdata[9]>>4;
|
||||
if (tmp_forecast == 0x02)
|
||||
forecast = 3;
|
||||
else if (tmp_forecast == 0x03)
|
||||
forecast = 4;
|
||||
else if (tmp_forecast == 0x06)
|
||||
forecast = 2;
|
||||
else if (tmp_forecast == 0x0C)
|
||||
forecast = 1;
|
||||
|
||||
// ----------------------------------
|
||||
// Output
|
||||
// ----------------------------------
|
||||
Serial.print("20;");
|
||||
PrintHexByte(PKSequenceNumber++);
|
||||
Serial.print(F(";Oregon BTHR;ID=")); // Label
|
||||
PrintHexByte(rc);
|
||||
PrintHexByte(osdata[2]);
|
||||
// ----------------------------------
|
||||
sprintf(pbuffer, ";TEMP=%04x;", temp);
|
||||
Serial.print( pbuffer );
|
||||
sprintf(pbuffer, "HUM=%02x;", hum);
|
||||
Serial.print( pbuffer );
|
||||
sprintf(pbuffer, "HSTATUS=%d;", comfort);
|
||||
Serial.print( pbuffer );
|
||||
sprintf(pbuffer, "BARO=%04x;", baro);
|
||||
Serial.print( pbuffer );
|
||||
sprintf(pbuffer, "BFORECAST=%d;", forecast);
|
||||
Serial.print( pbuffer );
|
||||
|
||||
//below is not correct, and for now discarded
|
||||
//if (((osdata[3] & 0x0F) & 0x04) != 0) {
|
||||
// Serial.print("BAT=LOW;");
|
||||
//} else {
|
||||
// Serial.print("BAT=OK;");
|
||||
//}
|
||||
Serial.println();
|
||||
} else
|
||||
// ==================================================================================
|
||||
// 2914 Rain Gauge:
|
||||
// 2d10 Rain Gauge:
|
||||
// 2a1d Rain Gauge: RGR126, RGR682, RGR918, RGR928, PCR122
|
||||
// 2A1D0065502735102063
|
||||
// 2+A+1+D+0+0+6+5+5+0+2+7+3+5+1+0+2+0=3e-a=34 != 63
|
||||
// 2+A+1+D+0+0+6+5+5+0+2+7+3+5+1+0+2+0+6=44-a=3A
|
||||
// ==================================================================================
|
||||
if(id == 0x2a1d || id == 0x2d10 || id == 0x2914) { // Rain sensor
|
||||
//Checksum - add all nibbles from 0 to 8, subtract 9 and compare
|
||||
/*
|
||||
int cs = 0;
|
||||
for (byte i = 0; i < pos-2; ++i) { //all but last byte
|
||||
cs += data[i] >> 4;
|
||||
cs += data[i] & 0x0F;
|
||||
}
|
||||
int csc = (data[8] >> 4) + ((data[9] & 0x0F)*16);
|
||||
cs -= 9; //my version as A fails?
|
||||
Serial.print(csc);
|
||||
Serial.print(" vs ");
|
||||
Serial.println(cs);
|
||||
*/
|
||||
rain = ((osdata[5]>>4) * 100) + ((osdata[5] & 0x0F) * 10) + (osdata[4] >> 4);
|
||||
raintot = ((osdata[7] >> 4) * 10) + (osdata[6]>>4);
|
||||
// ----------------------------------
|
||||
// Output
|
||||
// ----------------------------------
|
||||
Serial.print("20;");
|
||||
PrintHexByte(PKSequenceNumber++);
|
||||
Serial.print(F(";Oregon Rain;ID=")); // Label
|
||||
PrintHexByte(rc);
|
||||
PrintHexByte(osdata[3]);
|
||||
// ----------------------------------
|
||||
sprintf(pbuffer, ";RAIN=%04x;", rain);
|
||||
Serial.print( pbuffer );
|
||||
sprintf(pbuffer, "RAINTOT=%04x;", raintot);
|
||||
Serial.print( pbuffer );
|
||||
if ((osdata[3] & 0x0F) >= 4) {
|
||||
Serial.print(F("BAT=LOW;"));
|
||||
} else {
|
||||
Serial.print(F("BAT=OK;"));
|
||||
}
|
||||
Serial.println();
|
||||
} else
|
||||
// ==================================================================================
|
||||
// 2a19 Rain Gauge: PCR800
|
||||
// RAIN + BAT + CRC
|
||||
// ==================================================================================
|
||||
// OSV3 2A19048E399393250010
|
||||
// 01234567890123456789
|
||||
// 0 1 2 3 4 5 6 7 8 9
|
||||
// 2+A+1+9+0+4+8+E+3+9+9+3+9+3+2+5=5b-A=51 => 10
|
||||
if(id == 0x2a19) { // Rain sensor
|
||||
int sum = (osdata[9] >> 4);
|
||||
if ( checksum(3,9,sum) !=0) { // checksum = all nibbles 0-17 result is nibble 18
|
||||
//Serial.print("CRC Error, ");
|
||||
return false;
|
||||
}
|
||||
rain = ((osdata[5]>>4) * 100) + ((osdata[5] & 0x0F) * 10) + (osdata[4] >> 4);
|
||||
//Serial.print(" RainTotal=");
|
||||
//raintot = ((osdata[7] >> 4) * 10) + (osdata[6]>>4);
|
||||
//Serial.print(raintot);
|
||||
// ----------------------------------
|
||||
// Output
|
||||
// ----------------------------------
|
||||
Serial.print("20;");
|
||||
PrintHexByte(PKSequenceNumber++);
|
||||
Serial.print(F(";Oregon Rain2;ID=")); // Label
|
||||
PrintHexByte(rc);
|
||||
PrintHexByte(osdata[4]);
|
||||
// ----------------------------------
|
||||
sprintf(pbuffer,";RAIN=%04x;", rain);
|
||||
Serial.print( pbuffer );
|
||||
//sprintf(pbuffer, "RAINTOT=%04x;", raintot);
|
||||
//Serial.print( pbuffer );
|
||||
if ((osdata[3] & 0x0F) >= 4) {
|
||||
Serial.print(F("BAT=LOW;"));
|
||||
} else {
|
||||
Serial.print(F("BAT=OK;"));
|
||||
}
|
||||
Serial.println();
|
||||
} else
|
||||
// ==================================================================================
|
||||
// 1a89 Anemometer: WGR800
|
||||
// WIND DIR + SPEED + AV SPEED + CRC
|
||||
// ==================================================================================
|
||||
// OSV3 1A89048800C026400543
|
||||
// OSV3 1A89048800C00431103B
|
||||
// OSV3 1a89048848c00000003e W
|
||||
// OSV3 1a890488c0c00000003e E
|
||||
// 1A89042CB0C047000147
|
||||
// 0 1 2 3 4 5 6 7 8 9
|
||||
// 1+A+8+9+0+4+8+8+0+0+C+0+0+4+3+1+1+0=45-a=3b
|
||||
if(id == 0x1a89) { // Wind sensor
|
||||
if ( checksum(1,9,osdata[9]) !=0) return false;
|
||||
wdir=((osdata[4] >> 4) & 0x0f);
|
||||
// -------------
|
||||
wspeed = (osdata[6] >> 4) * 10;
|
||||
wspeed = wspeed + (osdata[6] &0x0f) * 100;
|
||||
wspeed = wspeed + (osdata[5] &0x0f);
|
||||
// -------------
|
||||
awspeed = (osdata[8] >> 4) * 100;
|
||||
awspeed = awspeed + (osdata[7] &0x0f) * 10;
|
||||
awspeed = awspeed + (osdata[7] >> 4);
|
||||
// ----------------------------------
|
||||
// Output
|
||||
// ----------------------------------
|
||||
Serial.print("20;");
|
||||
PrintHexByte(PKSequenceNumber++);
|
||||
Serial.print(F(";Oregon Wind;ID=")); // Label
|
||||
PrintHexByte(rc);
|
||||
PrintHexByte(osdata[2]);
|
||||
// ----------------------------------
|
||||
sprintf(pbuffer, ";WINDIR=%04d;", wdir);
|
||||
Serial.print( pbuffer );
|
||||
sprintf(pbuffer, "WINSP=%04x;", wspeed);
|
||||
Serial.print( pbuffer );
|
||||
sprintf(pbuffer, "AWINSP=%04x;", awspeed);
|
||||
Serial.print( pbuffer );
|
||||
if ((osdata[3] & 0x0F) >= 4) {
|
||||
Serial.print(F("BAT=LOW;"));
|
||||
} else {
|
||||
Serial.print(F("BAT=OK;"));
|
||||
}
|
||||
Serial.println();
|
||||
} else
|
||||
// ==================================================================================
|
||||
// 3a0d Anemometer: Huger-STR918, WGR918
|
||||
// 1984 Anemometer:
|
||||
// 1994 Anemometer:
|
||||
// WIND DIR + SPEED + AV SPEED + BAT + CRC
|
||||
// 3A0D006F400800000031
|
||||
// ==================================================================================
|
||||
if(id == 0x3A0D || id == 0x1984 || id == 0x1994 ) {
|
||||
if ( checksum(1,9,osdata[9]) !=0) {
|
||||
//Serial.print("CRC Error, ");
|
||||
return false;
|
||||
}
|
||||
wdir = ((osdata[5]>>4) * 100) + ((osdata[5] & 0x0F * 10) ) + (osdata[4] >> 4);
|
||||
wdir=wdir / 22.5;
|
||||
wspeed = ((osdata[7] & 0x0F) * 100) + ((osdata[6]>>4) * 10) + ((osdata[6] & 0x0F)) ;
|
||||
awspeed = ((osdata[8]>>4) * 100) + ((osdata[8] & 0x0F) * 10)+((osdata[7] >>4)) ;
|
||||
// ----------------------------------
|
||||
// Output
|
||||
// ----------------------------------
|
||||
Serial.print("20;");
|
||||
PrintHexByte(PKSequenceNumber++);
|
||||
Serial.print(F(";Oregon Wind2;ID=")); // Label
|
||||
PrintHexByte(rc);
|
||||
PrintHexByte(osdata[2]);
|
||||
// ----------------------------------
|
||||
sprintf(pbuffer, ";WINDIR=%04d;", wdir);
|
||||
Serial.print( pbuffer );
|
||||
sprintf(pbuffer, "WINSP=%04x;", wspeed);
|
||||
Serial.print( pbuffer );
|
||||
sprintf(pbuffer, "AWINSP=%04x;", awspeed);
|
||||
Serial.print( pbuffer );
|
||||
if ((osdata[3] & 0x0F) >= 4) {
|
||||
Serial.print(F("BAT=LOW;"));
|
||||
} else {
|
||||
Serial.print(F("BAT=OK;"));
|
||||
}
|
||||
Serial.println();
|
||||
} else
|
||||
// ==================================================================================
|
||||
// ea7c UV Sensor: UVN128, UV138
|
||||
// UV + BAT
|
||||
// NO CRC YET
|
||||
// ==================================================================================
|
||||
if(id == 0xea7c) {
|
||||
uv=((osdata[5] & 0x0F) * 10) + (osdata[4] >> 4);
|
||||
Serial.print(uv);
|
||||
// ----------------------------------
|
||||
// Output
|
||||
// ----------------------------------
|
||||
Serial.print("20;");
|
||||
PrintHexByte(PKSequenceNumber++);
|
||||
Serial.print(F(";Oregon UVN128/138;ID=")); // Label
|
||||
PrintHexByte(rc);
|
||||
PrintHexByte(osdata[2]);
|
||||
// ----------------------------------
|
||||
sprintf(pbuffer, ";UV=%04x;", uv);
|
||||
Serial.print( pbuffer );
|
||||
if ((osdata[3] & 0x0F) >= 4) {
|
||||
Serial.print(F("BAT=LOW;"));
|
||||
} else {
|
||||
Serial.print(F("BAT=OK;"));
|
||||
}
|
||||
Serial.println();
|
||||
} else
|
||||
// ==================================================================================
|
||||
// da78 UV Sensor: UVN800
|
||||
// UV
|
||||
// NO CRC YET
|
||||
// ==================================================================================
|
||||
if( id == 0xda78) {
|
||||
uv=(osdata[6] & 0xf0) + (osdata[5] &0x0f) ;
|
||||
// ----------------------------------
|
||||
// Output
|
||||
// ----------------------------------
|
||||
Serial.print("20;");
|
||||
PrintHexByte(PKSequenceNumber++);
|
||||
Serial.print(F(";Oregon UVN800;ID=")); // Label
|
||||
PrintHexByte(rc);
|
||||
PrintHexByte(osdata[2]);
|
||||
// ----------------------------------
|
||||
sprintf(pbuffer, ";UV=%04x;", uv);
|
||||
Serial.print( pbuffer );
|
||||
if ((osdata[3] & 0x0F) >= 4) {
|
||||
Serial.print(F("BAT=LOW;"));
|
||||
} else {
|
||||
Serial.print(F("BAT=OK;"));
|
||||
}
|
||||
Serial.println();
|
||||
} else
|
||||
// ==================================================================================
|
||||
// *aec Date&Time: RTGR328N
|
||||
// 8A EC 13 FC 60 81 43 91 11 30 0 0 0 ;
|
||||
// 8+A+E+C+1+3+F+C+6+0+8+1+4+3+9+1=6B -A=61 != 30
|
||||
// 8+A+E+C+1+3+F+C+6+0+8+1+4+3+9=6a-A=60 0=0
|
||||
// NO CRC YET
|
||||
//20;06;Oregon Unknown;DEBUG=8A EC 13 FC 60 81 43 91 11 30 0 0 0 ;
|
||||
//20;20;Oregon Unknown;DEBUG=8A EC 13 FC 40 33 44 91 11 30 0 0 0 ;
|
||||
|
||||
|
||||
// OSV3 2A19048E399393250010
|
||||
// 01234567890123456789
|
||||
// 0 1 2 3 4 5 6 7 8 9
|
||||
// 2+A+1+9+0+4+8+E+3+9+9+3+9+3+2+5=5b-A=51 => 10
|
||||
|
||||
// ==================================================================================
|
||||
// 8AEA1378077214924242C16CBD 21:49 29/04/2014
|
||||
// 0 1 2 3 4 5 6 7 8 9 0 1 2
|
||||
// 8+A+E+A+1+3+7+8+0+7+7+2+1+4+9+2+4+2+4+2+C+1+6+C=88 != BD
|
||||
// Date & Time
|
||||
// ==================================================================================
|
||||
// eac0 Ampere meter: cent-a-meter, OWL CM113, Electrisave
|
||||
// ==================================================================================
|
||||
if(id == 0xeac0) {
|
||||
//Serial.println("UNKNOWN LAYOUT");
|
||||
// ----------------------------------
|
||||
// Output
|
||||
// ----------------------------------
|
||||
Serial.print("20;");
|
||||
PrintHexByte(PKSequenceNumber++);
|
||||
// ----------------------------------
|
||||
Serial.print(F(";Oregon Unknown;DEBUG=")); // Label
|
||||
PrintHex8( osdata, 13);
|
||||
Serial.println(";");
|
||||
} else
|
||||
// ==================================================================================
|
||||
// 0x1a* / 0x2a* 0x3a** Power meter: OWL CM119
|
||||
// ==================================================================================
|
||||
// 0x628* Power meter: OWL CM180
|
||||
// ==================================================================================
|
||||
// OSV3 6284 3C 7801 D0
|
||||
// OSV3 6280 3C 2801 A0A8BA05 00 00 ?? ?? ??
|
||||
// ==================================================================================
|
||||
// 1a99 Anemometer: WGTR800
|
||||
// WIND + TEMP + HUM + CRC
|
||||
// ==================================================================================
|
||||
if(id == 0x1a99) { // Wind sensor
|
||||
//Serial.println("UNKNOWN LAYOUT");
|
||||
// ----------------------------------
|
||||
// Output
|
||||
// ----------------------------------
|
||||
Serial.print("20;");
|
||||
PrintHexByte(PKSequenceNumber++);
|
||||
// ----------------------------------
|
||||
Serial.print(F(";Oregon Unknown;DEBUG=")); // Label
|
||||
PrintHex8( osdata, 13);
|
||||
Serial.println(";");
|
||||
} else
|
||||
// ==================================================================================
|
||||
if( (id&0xf00)==0xA00 ) { // Any Oregon sensor with id xAxx
|
||||
// ----------------------------------
|
||||
// Output
|
||||
// ----------------------------------
|
||||
Serial.print("20;");
|
||||
PrintHexByte(PKSequenceNumber++);
|
||||
// ----------------------------------
|
||||
Serial.print(F(";Oregon Unknown;DEBUG=")); // Label
|
||||
PrintHex8( osdata, 13);
|
||||
Serial.println(";");
|
||||
}
|
||||
// ==================================================================================
|
||||
RawSignal.Repeats=true; // suppress repeats of the same RF packet
|
||||
RawSignal.Number=0;
|
||||
return true;
|
||||
}
|
||||
#endif // PLUGIN_048
|
|
@ -0,0 +1,78 @@
|
|||
//#######################################################################################################
|
||||
//## This Plugin is only for use with the RFLink software package ##
|
||||
//## Plugin-060 AlarmSensor ##
|
||||
//#######################################################################################################
|
||||
/*********************************************************************************************\
|
||||
* This protocol provides support for some Alarm sensors that are part of a Varel/Chubb/Ajax alarm
|
||||
*
|
||||
* Author : StuntTeam
|
||||
* 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!
|
||||
*********************************************************************************************
|
||||
* Changelog: v1.0 initial release
|
||||
*********************************************************************************************
|
||||
* Technical data:
|
||||
* Devices send 25 pulses, first pulse is part of the start bit. Remaining bits are Manchester encoded, 24 bits
|
||||
*
|
||||
* The PCB contains a Holtec HT12E Encoder chip
|
||||
* The PCB has two switch blocks: SW1 with switches 1-8 (Device code?)
|
||||
* SW2 with switches 1-4 (House code?)
|
||||
*
|
||||
* Sample:
|
||||
* 20;74;DEBUG;Pulses=26;Pulses(uSec)=425,425,800,875,350,875,350,875,350,875,350,875,350,875,350,875,350,400,800,875,350,400,825,875,350;
|
||||
* 1001101010101010 01100110
|
||||
* 10000000 1010
|
||||
\*********************************************************************************************/
|
||||
#define ALARMPIRV2_PULSECOUNT 26
|
||||
|
||||
#define ALARMPIRV2_PULSEMID 700/RAWSIGNAL_SAMPLE_RATE
|
||||
#define ALARMPIRV2_PULSEMAX 1000/RAWSIGNAL_SAMPLE_RATE
|
||||
#define ALARMPIRV2_PULSESHORT 550/RAWSIGNAL_SAMPLE_RATE
|
||||
#define ALARMPIRV2_PULSEMIN 250/RAWSIGNAL_SAMPLE_RATE
|
||||
|
||||
#ifdef PLUGIN_060
|
||||
boolean Plugin_060(byte function, char *string) {
|
||||
if (RawSignal.Number != ALARMPIRV2_PULSECOUNT) return false;
|
||||
unsigned long bitstream=0L;
|
||||
byte data[3];
|
||||
if (RawSignal.Pulses[1] > ALARMPIRV2_PULSESHORT) return false; // First pulse is start bit and should be short!
|
||||
for(byte x=2;x < ALARMPIRV2_PULSECOUNT;x=x+2) {
|
||||
if (RawSignal.Pulses[x] > ALARMPIRV2_PULSEMID) { // long pulse 800-875 (700-1000 accepted)
|
||||
if (RawSignal.Pulses[x] > ALARMPIRV2_PULSEMAX) return false; // pulse too long
|
||||
if (RawSignal.Pulses[x+1] > ALARMPIRV2_PULSEMID) return false; // invalid manchester code
|
||||
bitstream = bitstream << 1;
|
||||
} else { // short pulse 350-425 (250-550 accepted)
|
||||
if (RawSignal.Pulses[x] < ALARMPIRV2_PULSEMIN) return false; // pulse too short
|
||||
if (RawSignal.Pulses[x+1] < ALARMPIRV2_PULSEMID) return false; // invalid manchester code
|
||||
bitstream = (bitstream << 1) | 0x1;
|
||||
}
|
||||
}
|
||||
//==================================================================================
|
||||
// Prevent repeating signals from showing up
|
||||
//==================================================================================
|
||||
if( (SignalHash!=SignalHashPrevious) || (RepeatingTimer+2000<millis()) ){
|
||||
// not seen the RF packet recently
|
||||
if (bitstream == 0) return false;
|
||||
} else {
|
||||
// already seen the RF packet recently
|
||||
return true;
|
||||
}
|
||||
//==================================================================================
|
||||
// Output
|
||||
// ----------------------------------
|
||||
sprintf(pbuffer, "20;%02X;", PKSequenceNumber++); // Node and packet number
|
||||
Serial.print( pbuffer );
|
||||
// ----------------------------------
|
||||
Serial.print(F("X10;")); // Label
|
||||
sprintf(pbuffer, "ID=%04x;", (bitstream)&0xffff);
|
||||
Serial.print( pbuffer );
|
||||
Serial.print(F("SWITCH=01;"));
|
||||
Serial.print(F("CMD=ON;")); // this device does report movement only
|
||||
Serial.println();
|
||||
//==================================================================================
|
||||
RawSignal.Repeats=true; // suppress repeats of the same RF packet
|
||||
RawSignal.Number=0;
|
||||
return true;
|
||||
}
|
||||
#endif // PLUGIN_060
|
|
@ -0,0 +1,93 @@
|
|||
//#######################################################################################################
|
||||
//## This Plugin is only for use with the RFLink software package ##
|
||||
//## Plugin-061 AlarmSensor ##
|
||||
//#######################################################################################################
|
||||
/*********************************************************************************************\
|
||||
* This protocol provides support for some chinese Alarm "gadgets" (Motion detectors and door/window contacts)
|
||||
* Note that these modules are reported as X10 switches to the Home Automation software so that they work correctly
|
||||
*
|
||||
* Author : StuntTeam
|
||||
* 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!
|
||||
*********************************************************************************************
|
||||
* Technical data:
|
||||
* Devices send 50 pulses. Manchester encoded, 25 bits
|
||||
*
|
||||
* PIR Motion detection unit:
|
||||
* PCB contains 2 chips: biss0001 & ev1527
|
||||
* BISS0001 = Micro Power PIR Motion Detector IC
|
||||
* EV1527 = OTP Encoder, max. of 20 bits providing up to 1 million codes.
|
||||
*
|
||||
* Sample:
|
||||
* Pulses=50, Pulses(uSec)=900,225,200,850,225,850,825,225,225,850,225,850,825,225,225,850,200,850,225,850,825,225,225,850,825,225,225,850,825,225,825,225,825,225,825,225,825,225,825,225,825,225,225,850,225,850,825,225,225,
|
||||
* 100101100101100101011001100110101010101010010110
|
||||
* 01101101 1101010000000110 6D D406
|
||||
|
||||
* 20;9A;DEBUG;Pulses=50;Pulses(uSec)=475,925,400,950,1150,175,400,950,375,950,1125,200,1100,225,1100,250,1075,250,1075,275,1050,275,1050,275,1050,275,1050,275,275,1050,1050,275,300,1050,1050,275,300,1050,300,1050,1050,275,300,1050,275,1050,1050,275,275;
|
||||
* 010110010110101010101010101001100110010110010110
|
||||
* 00100111 1111110101001001 27 FD49
|
||||
* 11011000 0000001010110110 D8 02B6
|
||||
|
||||
* 1975,275,900,250,225,975,250,975,250,975,225,975,900,250,900,250,900,250,250,950,225,975,900,250,225,950,225,975,250,950,225,975,900,250,900,250,900,250,250,950,900,250,250,950,225,950,925,250,250;
|
||||
* 101001010101101010010110010101011010100110010110
|
||||
* 001111000110111100010110 3C6F16
|
||||
* 110000111001000011101001 c390E9
|
||||
\*********************************************************************************************/
|
||||
#define ALARMPIRV1_PULSECOUNT 50
|
||||
|
||||
#define ALARMPIRV1_PULSEMID 600/RAWSIGNAL_SAMPLE_RATE
|
||||
#define ALARMPIRV1_PULSEMAX 1300/RAWSIGNAL_SAMPLE_RATE
|
||||
#define ALARMPIRV1_PULSEMIN 150/RAWSIGNAL_SAMPLE_RATE
|
||||
|
||||
#ifdef PLUGIN_061
|
||||
boolean Plugin_061(byte function, char *string) {
|
||||
if (RawSignal.Number != ALARMPIRV1_PULSECOUNT) return false;
|
||||
if (RawSignal.Pulses[0]==63) return false; // No need to test, packet for plugin 63
|
||||
unsigned long bitstream=0L;
|
||||
unsigned long bitstream2=0L;
|
||||
//==================================================================================
|
||||
for(byte x=2;x<=48;x=x+2) {
|
||||
if (RawSignal.Pulses[x] > ALARMPIRV1_PULSEMID) {
|
||||
if (RawSignal.Pulses[x] > ALARMPIRV1_PULSEMAX) return false; // pulse too long
|
||||
if (RawSignal.Pulses[x-1] > ALARMPIRV1_PULSEMID) return false; // invalid pulse sequence 10/01
|
||||
bitstream = bitstream << 1;
|
||||
} else {
|
||||
if (RawSignal.Pulses[x] < ALARMPIRV1_PULSEMIN) return false; // pulse too short
|
||||
if (RawSignal.Pulses[x-1] < ALARMPIRV1_PULSEMID) return false; // invalid pulse sequence 10/01
|
||||
bitstream = (bitstream << 1) | 0x1;
|
||||
}
|
||||
}
|
||||
//==================================================================================
|
||||
// Prevent repeating signals from showing up
|
||||
//==================================================================================
|
||||
if( (SignalHash!=SignalHashPrevious) || (RepeatingTimer+2000<millis()) ){
|
||||
// not seen the RF packet recently
|
||||
if (bitstream == 0) return false;
|
||||
} else {
|
||||
// already seen the RF packet recently
|
||||
return true;
|
||||
}
|
||||
//==================================================================================
|
||||
bitstream2=(bitstream)>>16;
|
||||
if ( (bitstream2)==0xff) {
|
||||
if ( (bitstream)&0xffff==0xff) return false;
|
||||
}
|
||||
//==================================================================================
|
||||
// Output
|
||||
// ----------------------------------
|
||||
sprintf(pbuffer, "20;%02X;", PKSequenceNumber++); // Node and packet number
|
||||
Serial.print( pbuffer );
|
||||
// ----------------------------------
|
||||
Serial.print(F("X10;")); // Label
|
||||
sprintf(pbuffer, "ID=%06lx;",(bitstream)&0xffffff) ; // ID
|
||||
Serial.print( pbuffer );
|
||||
Serial.print(F("SWITCH=01;"));
|
||||
Serial.print(F("CMD=ON;")); // this device reports movement only
|
||||
Serial.println();
|
||||
//==================================================================================
|
||||
RawSignal.Repeats=true; // suppress repeats of the same RF packet
|
||||
RawSignal.Number=0;
|
||||
return true;
|
||||
}
|
||||
#endif // Plugin_061
|
|
@ -0,0 +1,76 @@
|
|||
//#######################################################################################################
|
||||
//## This Plugin is only for use with the RFLink software package ##
|
||||
//## Plugin-062 Chuango AlarmSensors ##
|
||||
//#######################################################################################################
|
||||
/*********************************************************************************************\
|
||||
* This protocol provides support for Chuango Alarm sensors (Motion detectors and door/window contacts)
|
||||
* Note that these modules are reported as X10 switches to the Home Automation software so that they work correctly
|
||||
*
|
||||
* Author : StuntTeam
|
||||
* 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!
|
||||
*********************************************************************************************
|
||||
* Technical data:
|
||||
* Devices send 50 pulses, 24 bits
|
||||
*
|
||||
* Sample:
|
||||
* 20;03;DEBUG;Pulses=50;Pulses(uSec)=1725,325,1650,325,1625,350,575,1400,1600,400,1525,475,450,1550,1475,500,1500,500,450,1475,550,1450,
|
||||
* 550,1425,1600,400,525,1475,1500,450,1500,525,1475,500,425,1525,475,1475,500,1450,525,1450,1575,400,1550,425,1500,500,400;
|
||||
* 20;03;DEBUG;Pulses=50;Pulses(uSec)=1620,420,1530,450,1560,390,510,1440,1560,420,1530,420,450,1530,1440,510,1440,540,360,1500,450,1470,480,1470,1560,390,510,1440,1530,420,1500,480,1470,570,330,1590,390,1530,450,1500,480,1470,1530,420,1530,420,1530,420,450,3360;
|
||||
* 101010011010011010010101100110101001010101101010 0
|
||||
* 00010010 01110100 01111000 = 0x 12 74 78
|
||||
\*********************************************************************************************/
|
||||
#define ALARMPIRV1_PULSECOUNT 50
|
||||
|
||||
#define ALARMPIRV1_PULSEMID 700/RAWSIGNAL_SAMPLE_RATE
|
||||
#define ALARMPIRV1_PULSEMAX 2000/RAWSIGNAL_SAMPLE_RATE
|
||||
#define ALARMPIRV1_PULSEMIN 150/RAWSIGNAL_SAMPLE_RATE
|
||||
|
||||
#ifdef PLUGIN_062
|
||||
boolean Plugin_062(byte function, char *string) {
|
||||
if (RawSignal.Number != ALARMPIRV1_PULSECOUNT) return false;
|
||||
if (RawSignal.Pulses[0]==63) return false; // No need to test, packet for plugin 63
|
||||
unsigned long bitstream=0L;
|
||||
//==================================================================================
|
||||
for(byte x=2;x<=48;x=x+2) {
|
||||
if (RawSignal.Pulses[x] > ALARMPIRV1_PULSEMID) {
|
||||
if (RawSignal.Pulses[x] > ALARMPIRV1_PULSEMAX) return false; // pulse too long
|
||||
if (RawSignal.Pulses[x-1] > ALARMPIRV1_PULSEMID) return false; // invalid pulse sequence 10/01
|
||||
bitstream = (bitstream << 1) | 0x1;
|
||||
} else {
|
||||
if (RawSignal.Pulses[x] < ALARMPIRV1_PULSEMIN) return false; // pulse too short
|
||||
if (RawSignal.Pulses[x-1] < ALARMPIRV1_PULSEMID) return false; // invalid pulse sequence 10/01
|
||||
bitstream = bitstream << 1;
|
||||
}
|
||||
}
|
||||
//==================================================================================
|
||||
// Prevent repeating signals from showing up
|
||||
//==================================================================================
|
||||
if( (SignalHash!=SignalHashPrevious) || (RepeatingTimer+2000<millis()) ){
|
||||
// not seen the RF packet recently
|
||||
if (bitstream == 0) return false;
|
||||
} else {
|
||||
// already seen the RF packet recently
|
||||
return true;
|
||||
}
|
||||
//==================================================================================
|
||||
// Validity checks
|
||||
//==================================================================================
|
||||
// Output
|
||||
// ----------------------------------
|
||||
sprintf(pbuffer, "20;%02X;", PKSequenceNumber++); // Node and packet number
|
||||
Serial.print( pbuffer );
|
||||
// ----------------------------------
|
||||
Serial.print(F("Chuango;")); // Label
|
||||
sprintf(pbuffer, "ID=%06lx;",(bitstream)&0xffffff) ; // ID
|
||||
Serial.print( pbuffer );
|
||||
Serial.print(F("SWITCH=02;"));
|
||||
Serial.print(F("CMD=ON;")); // this device reports movement only
|
||||
Serial.println();
|
||||
//==================================================================================
|
||||
RawSignal.Repeats=true; // suppress repeats of the same RF packet
|
||||
RawSignal.Number=0;
|
||||
return true;
|
||||
}
|
||||
#endif // Plugin_062
|
|
@ -0,0 +1,83 @@
|
|||
//#######################################################################################################
|
||||
//## This Plugin is only for use with the RFLink software package ##
|
||||
//## Plugin-063 Oregon PIR/LED/ALARM ##
|
||||
//#######################################################################################################
|
||||
/*********************************************************************************************\
|
||||
* This plugin provides support for Oregon PIR/LED/ALARM devices
|
||||
*
|
||||
* Author : StuntTeam
|
||||
* 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!
|
||||
*********************************************************************************************
|
||||
* Technical data:
|
||||
* Devices send 50/52 pulses using typical Oregon bit encoding
|
||||
*
|
||||
* Sample:
|
||||
* 570,390,570,360,570,360,540,360,540,360,570,360,570,330,570,330,570,330,570,330,570,330,570,360,540,360,540,360,1110,330,570,900,1110,900,540,330,570,330,1110,900,1110,360,540,360,540,900,1110,330,570,330,570,1620
|
||||
* 00101110 10001000 = 2E88
|
||||
\*********************************************************************************************/
|
||||
#define OREGON_PLA_PULSECOUNT 52
|
||||
|
||||
#ifdef PLUGIN_063
|
||||
boolean Plugin_063(byte function, char *string) {
|
||||
if (RawSignal.Pulses[0] != 63) return false; // Only accept RF packets converted by plugin 1
|
||||
RawSignal.Pulses[0]=0;
|
||||
if ((RawSignal.Number < OREGON_PLA_PULSECOUNT-2) || (RawSignal.Number > OREGON_PLA_PULSECOUNT) ) return false;
|
||||
unsigned long bitstream=0L;
|
||||
//==================================================================================
|
||||
byte bits=0;
|
||||
byte rfbit = 1;
|
||||
|
||||
if ( (RawSignal.Number < 50) || (RawSignal.Number > 52)) return false;
|
||||
// Check preamble
|
||||
for(byte x=1;x<28;x=x+2){
|
||||
if (RawSignal.Pulses[x]*RawSignal.Multiply > 600) return false;
|
||||
if (RawSignal.Pulses[x+1]*RawSignal.Multiply > 600) return false;
|
||||
}
|
||||
// Check bits
|
||||
for(byte x=29;x<=RawSignal.Number;x++){
|
||||
if (RawSignal.Pulses[x]*RawSignal.Multiply > 600) { // toggle bit value
|
||||
if (RawSignal.Pulses[x]*RawSignal.Multiply > 1600) break; // done..
|
||||
rfbit = (~rfbit)&1;
|
||||
bitstream = (bitstream << 1) | rfbit;
|
||||
if (RawSignal.Pulses[x+1]*RawSignal.Multiply < 600) x++;
|
||||
} else {
|
||||
bitstream = (bitstream << 1) | rfbit; // short pulse keep bit value
|
||||
if (RawSignal.Pulses[x+1]*RawSignal.Multiply < 600) x++;
|
||||
}
|
||||
}
|
||||
//==================================================================================
|
||||
// Prevent repeating signals from showing up
|
||||
//==================================================================================
|
||||
if( (SignalHash!=SignalHashPrevious) || (RepeatingTimer+2000<millis()) ){
|
||||
// not seen the RF packet recently
|
||||
if (bitstream == 0) return false;
|
||||
} else {
|
||||
// already seen the RF packet recently
|
||||
return true;
|
||||
}
|
||||
//==================================================================================
|
||||
// calculate sensor and channel
|
||||
bitstream=(bitstream)>>4;
|
||||
bits=(bitstream)&0x3;
|
||||
bits=bits+0x30; // signal 3 for plugin 63
|
||||
//==================================================================================
|
||||
// Output
|
||||
// ----------------------------------
|
||||
sprintf(pbuffer, "20;%02X;", PKSequenceNumber++); // Node and packet number
|
||||
Serial.print( pbuffer );
|
||||
// ----------------------------------
|
||||
Serial.print(F("X10;")); // Label
|
||||
sprintf(pbuffer, "ID=%06lx;",(bitstream)&0xffffff) ; // ID + channel number
|
||||
Serial.print( pbuffer );
|
||||
sprintf(pbuffer, "SWITCH=%02x;", bits); // channel number
|
||||
Serial.print( pbuffer );
|
||||
Serial.print(F("CMD=ON;")); // this device reports movement only
|
||||
Serial.println();
|
||||
//==================================================================================
|
||||
RawSignal.Repeats=true; // suppress repeats of the same RF packet
|
||||
RawSignal.Number=0;
|
||||
return true;
|
||||
}
|
||||
#endif // Plugin_063
|
|
@ -0,0 +1,163 @@
|
|||
//#######################################################################################################
|
||||
//## This Plugin is only for use with the RFLink software package ##
|
||||
//## Plugin-70 Select Plus Wireless Doorbell ##
|
||||
//#######################################################################################################
|
||||
/*********************************************************************************************\
|
||||
* This Plugin takes care of reception of the Select Plus wireless doorbell (Sold at Action for 6 euro's)
|
||||
* PCB markings: Quhwa QH-C-CE-3V aka QH-832AC
|
||||
* Also sold as "1 by One" and "Delta" wireless doorbell.
|
||||
*
|
||||
* Author : StuntTeam
|
||||
* 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!
|
||||
*********************************************************************************************
|
||||
* Changelog: v1.0 initial release
|
||||
*********************************************************************************************
|
||||
* Technical information:
|
||||
*
|
||||
* There are two known models:
|
||||
* SelectPlus (200689103 - Black - Datecode:0614) also sold as "1 by One" (O00 QH-0031)
|
||||
* PCB details: Quhwa, QH-C-CE-3V, 09.10.16, CPU: MC908T
|
||||
* SelectPlus (200689101 - White - Datecode:0914)
|
||||
* PCB details: Quhwa, QH-C-CE-3V, REV1.0, CPU: MC908T
|
||||
*
|
||||
* Each frame is 35 pulses long. It is composed of:
|
||||
* 101011001010110010110011010 10101010
|
||||
* The first block appears to be an unique ID
|
||||
* The second block appears to be some kind of identifier which always is 0xAA (10101010)
|
||||
* Converting the pulses into bits results in a 13 bit unique address and a 4 bit identifier:
|
||||
*
|
||||
* B) 1110000110011 0000 => 1C33 0 B)lack push button
|
||||
* W) 1101110110100 0000 => 1BB4 0 W)hite push button
|
||||
*
|
||||
* Note: The transmitter sends 43 times the same packet when the bell button is pressed
|
||||
* the retransmit is killed to prevent reporting the same press multiple times
|
||||
*
|
||||
* Sample:
|
||||
* B) 20;62;DEBUG;Pulses=36;Pulses(uSec)=1000,1000,225,1000,225,1000,225,300,900,300,900,300,900,300,900,1000,225,1000,225,300,925,300,900,1000,225,1000,225,275,900,300,900,300,900,300,900;
|
||||
* W) 20;A2;DEBUG;Pulses=36;Pulses(uSec)=325,950,250,950,250,250,925,950,250,950,250,950,250,275,925,950,250,950,250,250,925,950,250,275,925,250,925,275,925,250,925,275,925,275,925;
|
||||
* w) 20;66;DEBUG;Pulses=36;Pulses(uSec)=650,2000,550,2000,550,550,2000,2000,550,2000,550,2000,550,550,2000,2000,550,2000,550,550,2000,2000,550,550,2000,550,2000,550,1950,550,2000,550,2000,550,2000;
|
||||
* b) 20;05;DEBUG;Pulses=36;Pulses(uSec)=2100,2100,500,2050,500,2100,500,600,1950,600,1950,600,1950,600,1950,2050,500,2050,500,600,1950,600,1950,2100,500,2050,500,600,1950,600,1950,600,1950,600,1950;
|
||||
\*********************************************************************************************/
|
||||
#define SELECTPLUS_PULSECOUNT 36
|
||||
#define SELECTPLUS_PULSEMID 650/RAWSIGNAL_SAMPLE_RATE
|
||||
#define SELECTPLUS_PULSEMAX 2125/RAWSIGNAL_SAMPLE_RATE
|
||||
|
||||
#ifdef PLUGIN_070
|
||||
boolean Plugin_070(byte function, char *string) {
|
||||
if (RawSignal.Number !=SELECTPLUS_PULSECOUNT) return false;
|
||||
unsigned long bitstream=0L;
|
||||
byte checksum=0;
|
||||
//==================================================================================
|
||||
// get bytes
|
||||
for(byte x=2;x < SELECTPLUS_PULSECOUNT;x=x+2) {
|
||||
if (RawSignal.Pulses[x] < SELECTPLUS_PULSEMID) {
|
||||
if (RawSignal.Pulses[x+1] < SELECTPLUS_PULSEMID) return false; // invalid pulse sequence 10/01
|
||||
bitstream = (bitstream << 1);
|
||||
} else {
|
||||
if (RawSignal.Pulses[x] > SELECTPLUS_PULSEMAX) return false; // invalid pulse duration, pulse too long
|
||||
if (RawSignal.Pulses[x+1] > SELECTPLUS_PULSEMID) return false; // invalid pulse sequence 10/01
|
||||
bitstream = (bitstream << 1) | 0x1;
|
||||
}
|
||||
}
|
||||
if (bitstream == 0) return false; // sanity check
|
||||
//==================================================================================
|
||||
// Prevent repeating signals from showing up
|
||||
//==================================================================================
|
||||
if((SignalHash!=SignalHashPrevious) || ((RepeatingTimer+2000)<millis()) || (SignalCRC != bitstream) ) {
|
||||
SignalCRC=bitstream; // not seen the RF packet recently
|
||||
} else {
|
||||
return true; // already seen the RF packet recently
|
||||
}
|
||||
//==================================================================================
|
||||
// all bytes received, make sure checksum is okay
|
||||
//==================================================================================
|
||||
checksum = (bitstream)&0xf; // Second block
|
||||
if (checksum != 0) return false; // last 4 bits should always be 0
|
||||
//==================================================================================
|
||||
// Output
|
||||
// ----------------------------------
|
||||
Serial.print("20;");
|
||||
PrintHexByte(PKSequenceNumber++);
|
||||
Serial.print(F(";SelectPlus;")); // Label
|
||||
// ----------------------------------
|
||||
sprintf(pbuffer, "ID=%04x;",((bitstream)>>4)&0xffff ); // ID
|
||||
Serial.print( pbuffer );
|
||||
Serial.print(F("SWITCH=1;CMD=ON;"));
|
||||
Serial.print(F("CHIME=01;"));
|
||||
Serial.println();
|
||||
//==================================================================================
|
||||
RawSignal.Repeats=true; // suppress repeats of the same RF packet
|
||||
RawSignal.Number=0; // do not process the packet any further
|
||||
return true;
|
||||
}
|
||||
#endif // PLUGIN_070
|
||||
|
||||
#ifdef PLUGIN_TX_070
|
||||
void SelectPlus_Send(unsigned long address);
|
||||
|
||||
boolean PluginTX_070(byte function, char *string) {
|
||||
boolean success=false;
|
||||
unsigned long bitstream=0L;
|
||||
//10;SELECTPLUS;001c33;1;OFF;
|
||||
//012345678901234567890123456
|
||||
if (strncasecmp(InputBuffer_Serial+3,"SELECTPLUS;",11) == 0) {
|
||||
InputBuffer_Serial[12]=0x30;
|
||||
InputBuffer_Serial[13]=0x78;
|
||||
InputBuffer_Serial[20]=0;
|
||||
bitstream=str2int(InputBuffer_Serial+12);
|
||||
bitstream=bitstream << 4;
|
||||
SelectPlus_Send(bitstream); // Send RF packet
|
||||
success=true;
|
||||
}
|
||||
return success;
|
||||
}
|
||||
|
||||
void SelectPlus_Send(unsigned long address) {
|
||||
int fpulse = 364; // Pulse witdh in microseconds
|
||||
int fretrans = 16; // number of RF packet retransmissions
|
||||
uint32_t fdatabit;
|
||||
uint32_t fdatamask = 0x10000;
|
||||
uint32_t fsendbuff;
|
||||
|
||||
digitalWrite(PIN_RF_RX_VCC,LOW); // Power off the RF receiver (if wired that way) to protect against interference
|
||||
digitalWrite(PIN_RF_TX_VCC,HIGH); // Enable 433Mhz transmitter
|
||||
delayMicroseconds(TRANSMITTER_STABLE_DELAY); // short delay to let the transmitter become stable (Note: Aurel RTX MID needs 500µS/0,5ms)
|
||||
|
||||
for (int nRepeat = 0; nRepeat <= fretrans; nRepeat++) {
|
||||
fsendbuff=address;
|
||||
// send SYNC 3P High
|
||||
digitalWrite(PIN_RF_TX_DATA, HIGH);
|
||||
delayMicroseconds(fpulse * 3);
|
||||
// end send SYNC
|
||||
// Send command
|
||||
for (int i = 0; i < 17;i++) { // SelectPlus address is only 13 bits, last 4 bits are always zero
|
||||
// read data bit7
|
||||
fdatabit = fsendbuff & fdatamask; // Get most left bit
|
||||
fsendbuff = (fsendbuff << 1); // Shift left
|
||||
|
||||
if (fdatabit != fdatamask) { // Write 0
|
||||
digitalWrite(PIN_RF_TX_DATA, LOW); // short low
|
||||
delayMicroseconds(fpulse * 1);
|
||||
digitalWrite(PIN_RF_TX_DATA, HIGH); // long high
|
||||
delayMicroseconds(fpulse * 3);
|
||||
} else { // Write 1
|
||||
digitalWrite(PIN_RF_TX_DATA, LOW);
|
||||
delayMicroseconds(fpulse * 3); // long low
|
||||
digitalWrite(PIN_RF_TX_DATA, HIGH);
|
||||
delayMicroseconds(fpulse * 1); // short high
|
||||
}
|
||||
}
|
||||
digitalWrite(PIN_RF_TX_DATA, LOW); // and lower the signal
|
||||
if (nRepeat < fretrans) {
|
||||
delayMicroseconds(fpulse * 16); // delay between RF transmits
|
||||
}
|
||||
|
||||
}
|
||||
delayMicroseconds(TRANSMITTER_STABLE_DELAY); // short delay to let the transmitter become stable (Note: Aurel RTX MID needs 500µS/0,5ms)
|
||||
digitalWrite(PIN_RF_TX_VCC,LOW); // Disable the 433Mhz transmitter
|
||||
digitalWrite(PIN_RF_RX_VCC,HIGH); // Enable the 433Mhz receiver
|
||||
RFLinkHW();
|
||||
}
|
||||
#endif // PLUGIN_070
|
|
@ -0,0 +1,95 @@
|
|||
//#######################################################################################################
|
||||
//## This Plugin is only for use with the RFLink software package ##
|
||||
//## Plugin-71 Plieger York doorbell ##
|
||||
//#######################################################################################################
|
||||
/*********************************************************************************************\
|
||||
* This plugin takes care of decoding the Plieger York Doorbell protocol
|
||||
*
|
||||
* Author : StuntTeam
|
||||
* 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!
|
||||
*********************************************************************************************
|
||||
* Changelog: v1.0 initial release
|
||||
*********************************************************************************************
|
||||
* Technical Information:
|
||||
* Decodes signals from a Plieger York Doorbell, (66 pulses, 32 bits, 433 MHz).
|
||||
* Plieger Message Format:
|
||||
* 0000000001010101 00000000 00011100 c2 0x1c
|
||||
* 00000011 c3 0x03
|
||||
* 11100000 c1 0xE0
|
||||
* -------- 8 bits chime number (3 chimes, can be changed with a jumped on the transmitter)
|
||||
* -------- 8 bits always 0
|
||||
* ---------------- 16 bits code which can be changed with a button on the inside of the transmitter
|
||||
*
|
||||
* Note: The transmitter sends two times the same packet when the bell button is pressed
|
||||
* the retransmit is killed to prevent reporting the same press twice
|
||||
*
|
||||
* Sample packet: (Nodo Pulse timing)
|
||||
* Pulses=66, Pulses(uSec)=700,250,275,725,750,250,275,725,750,250,275,725,750,250,275,725,750,250,
|
||||
* 275,725,750,250,275,725,750,250,275,725,750,250,275,725,275,725,275,725,275,725,275,725,275,725,
|
||||
* 275,725,275,725,275,725,275,725,275,725,275,725,750,250,750,250,750,250,275,725,275,725,225,
|
||||
* 20;8C;DEBUG;Pulses=66;Pulses(uSec)=1800,550,600,1500,1600,550,600,1500,1600,550,600,1500,1600,550,600,1500,1600,550,600,1500,1600,500,600,1500,1600,550,600,1550,1600,550,600,1500,600,1500,600,1500,600,1500,600,1500,600,1500,600,1500,600,1500,600,1500,600,1500,600,1500,600,1500,1600,550,1600,500,1600,550,600,1500,600,1500,450;
|
||||
* 20;2D;DEBUG;Pulses=66;Pulses(uSec)=875,275,300,750,800,275,300,750,800,275,300,750,800,275,300,750,800,275,300,750,800,250,300,750,800,275,275,750,800,275,300,750,300,750,300,750,300,750,300,750,300,750,300,750,300,750,300,750,300,750,300,750,300,750,800,275,800,275,800,250,300,750,300,750,225;
|
||||
* 20;2E;Plieger York;ID=aaaa;SWITCH=1;CMD=ON;CHIME=02;
|
||||
\*********************************************************************************************/
|
||||
#define PLIEGER_PULSECOUNT 66
|
||||
#define PLIEGER_PULSEMID 700/RAWSIGNAL_SAMPLE_RATE
|
||||
#define PLIEGER_PULSEMAX 1900/RAWSIGNAL_SAMPLE_RATE
|
||||
|
||||
#ifdef PLUGIN_071
|
||||
boolean Plugin_071(byte function, char *string) {
|
||||
if (RawSignal.Number != PLIEGER_PULSECOUNT) return false;
|
||||
unsigned long bitstream=0L;
|
||||
unsigned int id=0;
|
||||
byte chime=0;
|
||||
//==================================================================================
|
||||
// get all 32 bits
|
||||
for(byte x=1;x <=PLIEGER_PULSECOUNT-2;x+=2) {
|
||||
if(RawSignal.Pulses[x] > PLIEGER_PULSEMID) {
|
||||
if (RawSignal.Pulses[x] > PLIEGER_PULSEMAX) return false;
|
||||
if (RawSignal.Pulses[x+1] > PLIEGER_PULSEMID) return false; // Valid Manchester check
|
||||
bitstream = (bitstream << 1) | 0x1;
|
||||
} else {
|
||||
if (RawSignal.Pulses[x+1] < PLIEGER_PULSEMID) return false; // Valid Manchester check
|
||||
bitstream = (bitstream << 1);
|
||||
}
|
||||
}
|
||||
//==================================================================================
|
||||
// Prevent repeating signals from showing up
|
||||
//==================================================================================
|
||||
if( (SignalHash!=SignalHashPrevious) || (RepeatingTimer+1000<millis()) ){
|
||||
// not seen the RF packet recently
|
||||
if (bitstream == 0) return false; // sanity check
|
||||
} else {
|
||||
// already seen the RF packet recently
|
||||
return true;
|
||||
}
|
||||
//==================================================================================
|
||||
// first perform two checks to validate the data
|
||||
if (((bitstream >> 8) &0xff) != 0x00) return false; // these 8 bits are always 0
|
||||
chime=bitstream &0xff;
|
||||
if (chime != 0x1c && chime !=0x03 && chime != 0xE0) return false; // the chime number can only have 3 values
|
||||
//==================================================================================
|
||||
id=(bitstream >> 16) & 0xffff; // get 16 bits unique address
|
||||
if (chime == 0xE0) chime =1;
|
||||
if (chime == 0x1C) chime =2;
|
||||
//==================================================================================
|
||||
// Output
|
||||
// ----------------------------------
|
||||
Serial.print("20;");
|
||||
PrintHexByte(PKSequenceNumber++);
|
||||
Serial.print(F(";Plieger;")); // Label
|
||||
// ----------------------------------
|
||||
sprintf(pbuffer, "ID=%04x;", id); // ID
|
||||
Serial.print( pbuffer );
|
||||
Serial.print("SWITCH=1;CMD=ON;");
|
||||
sprintf(pbuffer, "CHIME=%02x;", chime); // chime number
|
||||
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;
|
||||
}
|
||||
#endif // PLUGIN_071
|
|
@ -0,0 +1,139 @@
|
|||
//#######################################################################################################
|
||||
//## This Plugin is only for use with the RFLink software package ##
|
||||
//## Plugin-072 Byron Wireless Doorbell ##
|
||||
//#######################################################################################################
|
||||
/*********************************************************************************************\
|
||||
* This Plugin takes care of reception And sending of the Byron SX doorbell
|
||||
*
|
||||
* Author : Maurice Ruiter (Dodge)
|
||||
* 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!
|
||||
*********************************************************************************************
|
||||
* Changelog: v1.0 initial release
|
||||
*********************************************************************************************
|
||||
* Technical information:
|
||||
* 26 pulses, manchester code, 12 bits
|
||||
*
|
||||
* 111111110001
|
||||
* AAAAAAAABBBB
|
||||
*
|
||||
* A = 8 bit Address
|
||||
* B = chime number
|
||||
* Valid chime numbers: 1,2,6,9,a,c,d,e ?
|
||||
* ---------------------------------------------------------
|
||||
* 20;25;DEBUG;Pulses=26;Pulses(uSec)=275,250,250,525,250,225,250,525,250,225,250,525,525,225,250,525,525,225,250,225,250,225,250,525,525;
|
||||
* 20;F0;DEBUG;Pulses=511;Pulses(uSec)=450,225,575,200,575,225,575,200,575,200,575,200,575,225,575,550,250,200,575,200,575,200,575,550,250,2825,250,200,575,200,575,200,575,225,575,200,575,200,575,200,575,550,250,200,575,200,575,200,575,525,250,2825,250,200,575,200,575,200,575,225,575,200,575,200,575,200,575,550,250,225,575,200,575,225,575,550,250,2825,250,200,575,200,575,200,575,200,575,200,575,200,575,200,575,550,250,200,575,225,575,200,575,550,250,2850,250,200,575,200,575,200,575,200,575,200,575,200,575,200,575,550,250,225,575,200,575,200,575,550,250,2850,225,225,575,200,575,225,575,200,575,200,575,200,575,200,575,550,250,225,575,200,575,200,575,525,250,2825,250,225,575,200,575,200,575,200,575,200,575,200,575,200,575,550,250,200,575,200,575,225,575,525,250,2825,250,225,575,225,575,200,575,200,575,200,575,225,575,200,575,550,250,200,575,200,575,200,575,550,250,2825,250,200,575,200,575,200,575,225,575,225,575,200,575,200,575,550,250,200,575,200,575,200,575,525,250,2825,250,200,575,200,575,200,575,200,575,200,575,200,575,200,575,550,250,225,575,200,575,225,575,550,250,2825,250,200,575,200,575,200,575,200,575,200,575,225,575,200,575,550,250,200,575,225,575,200,575,550,250,2850,250,200,575,200,575,200,575,200,575,200,575,200,575,200,575,550,250,225,575,225,575,200,575,550,250,2850,250,200,575,200,575,225,575,200,575,200,575,200,575,200,575,550,250,225,575,200,575,200,575,550,250,2825,250,200,575,200,575,200,575,200,575,225,575,200,575,200,575,550,250,200,575,200,575,225,575,550,250,2825,250,200,575,225,575,200,575,200,575,200,575,225,575,200,575,525,250,200,575,200,575,200,575,550,250,2825,250,200,575,225,575,200,575,200,575,200,575,225,575,200,575,550,250,200,575,200,575,200,575,525,250,2825,250,200,575,200,575,225,575,200,575,200,575,200,575,225,575,550,250,200,575,225,575,225,575,525,250,2825,250,200,575,200,575,200,575,200,575,225,575,200,575,225,575,550,250,225,575,200,575,225,575,550,250,2825,250,200,575,200,575,200,575,200,575,200,575,200,575,225,575,525,250,225,575,200,575,225,575,550,250,2850,225,225,575,200,575,225,575,200,575,200,575,200,575,200,575,525;
|
||||
* 20;31;DEBUG;Pulses=511;Pulses(uSec)=450,550,250,550,250,550,250,550,250,525,250,525,250,550,250,550,250,225,575,200,575,200,575,550,250,2825,250,550,250,550,250,550,250,550,250,550,250,550,250,525,250,525,250,200,575,225,575,200,575,550,250,2825,250,525,250,550,250,550,250,550,250,550,250,550,250,550,250,550,250,200,575,200,575,200,575,525,250,2825,250,550,250,550,250,525,250,550,250,550,250,550,250,550,250,550,250,200,575,200,575,200,575,525,250,2825,250,550,250,525,250,525,250,525,250,550,250,550,250,550,250,550,250,225,575,200,575,200,575,525,250,2825,250,550,250,525,250,525,250,525,250,525,250,550,250,550,250,550,250,200,575,200,575,225,575,550,250,2825,225,550,250,525,250,525,250,550,250,550,250,525,250,525,250,525,250,225,575,200,575,225,575,550,250,2850,250,550,250,550,250,550,250,525,250,525,250,525,250,550,250,550,250,225,575,200,575,225,575,550,250,2850,225,550,250,550,250,550,250,550,250,525,250,525,250,525,250,550,250,200,575,200,575,200,575,525,250,2825,250,550,250,550,250,550,250,550,250,550,250,550,250,525,250,525,250,200,575,200,575,200,575,550,250,2825,250,525,250,550,250,550,250,550,250,550,250,550,250,550,250,550,250,200,575,200,575,200,575,550,250,2825,250,550,250,525,250,525,250,525,250,550,250,550,250,550,250,550,250,200,575,200,575,200,575,525,250,2825,250,550,250,550,250,550,250,525,250,550,250,550,250,550,250,550,250,200,575,200,575,225,575,525,250,2825,250,550,250,550,250,525,250,525,250,550,250,550,250,525,250,525,250,200,575,225,575,225,575,550,250,2850,250,550,250,550,250,525,250,525,250,525,250,550,250,550,250,550,250,200,575,225,575,200,575,550,250,2850,250,550,250,550,250,550,250,550,250,525,250,525,250,550,250,550,250,225,575,225,575,200,575,550,250,2825,250,550,250,550,250,550,250,550,250,550,250,550,250,550,250,525,250,200,575,200,575,200,575,550,250,2825,250,525,250,550,250,550,250,550,250,550,250,550,250,550,250,525,250,200,575,200,575,200,575,550,250,2825,250,525,250,550,250,550,250,550,250,550,250,550,250,550,250,550,250,200,575,200,575,200,575,525,250,2825,250,550,250,550,250,525,250,525,250,525,250,550,250,550,250,550;
|
||||
* 20;25;DEBUG;Pulses=26;Pulses(uSec)=250,550,250,550,250,550,250,550,250,550,250,550,250,525,250,525,250,200,575,225,575,200,575,550,250;
|
||||
\*********************************************************************************************/
|
||||
#define PLUGIN_ID 72
|
||||
#define BYRON_PULSECOUNT 26
|
||||
|
||||
#define BYRONSTART 3000
|
||||
#define BYRONSPACE 250
|
||||
#define BYRONLOW 350
|
||||
#define BYRONHIGH 675
|
||||
|
||||
#ifdef PLUGIN_072
|
||||
boolean Plugin_072(byte function, char *string){
|
||||
if (RawSignal.Number !=BYRON_PULSECOUNT) return false;
|
||||
if (RawSignal.Pulses[0] != PLUGIN_ID) return false; // only accept plugin1 translated packets
|
||||
if (RawSignal.Pulses[1]*RAWSIGNAL_SAMPLE_RATE > 425) return false; // first pulse is start bit and must be short
|
||||
unsigned long bitstream=0L;
|
||||
//==================================================================================
|
||||
for(byte x=2;x < BYRON_PULSECOUNT-1;x=x+2) {
|
||||
if (RawSignal.Pulses[x]*RAWSIGNAL_SAMPLE_RATE < 350) { // 200-275 (150-350 is accepted)
|
||||
if (RawSignal.Pulses[x]*RAWSIGNAL_SAMPLE_RATE < 150) return false; // pulse too short
|
||||
if (RawSignal.Pulses[x+1]*RAWSIGNAL_SAMPLE_RATE < 350) return false; // bad manchester code
|
||||
bitstream = (bitstream << 1);
|
||||
} else { // 500-575 (450-650 is accepted)
|
||||
if (RawSignal.Pulses[x+1]*RAWSIGNAL_SAMPLE_RATE > 450) return false; // bad manchester code
|
||||
if (RawSignal.Pulses[x]*RAWSIGNAL_SAMPLE_RATE < 450) return false; // pulse too short
|
||||
if (RawSignal.Pulses[x]*RAWSIGNAL_SAMPLE_RATE > 650) return false; // pulse too long
|
||||
bitstream = (bitstream << 1) | 0x1;
|
||||
}
|
||||
}
|
||||
//==================================================================================
|
||||
// Prevent repeating signals from showing up
|
||||
//==================================================================================
|
||||
if( (SignalHash!=SignalHashPrevious) || (RepeatingTimer+1000<millis()) ){
|
||||
// not seen the RF packet recently
|
||||
if (bitstream == 0) return false; // sanity check
|
||||
} else {
|
||||
// already seen the RF packet recently
|
||||
return true;
|
||||
}
|
||||
//==================================================================================
|
||||
// Output
|
||||
// ----------------------------------
|
||||
Serial.print("20;");
|
||||
PrintHexByte(PKSequenceNumber++);
|
||||
Serial.print(F(";Byron SX;")); // Label
|
||||
// ----------------------------------
|
||||
sprintf(pbuffer, "ID=%04x;", ((bitstream)>>4)&0xff);// ID
|
||||
Serial.print( pbuffer );
|
||||
Serial.print(F("SWITCH=1;CMD=ON;"));
|
||||
sprintf(pbuffer, "CHIME=%02x;", (bitstream)&0xf); // chime number
|
||||
Serial.print( pbuffer );
|
||||
Serial.println();
|
||||
//==================================================================================
|
||||
RawSignal.Repeats=true; // suppress repeats of the same RF packet
|
||||
RawSignal.Number=0;
|
||||
return true;
|
||||
}
|
||||
#endif // PLUGIN_072
|
||||
|
||||
#ifdef PLUGIN_TX_072
|
||||
boolean PluginTX_072(byte function, char *string) {
|
||||
boolean success=false;
|
||||
//10;BYRON;112233;01;OFF;
|
||||
//01234567890123456789012
|
||||
if (strncasecmp(InputBuffer_Serial+3,"BYRON;",5) == 0) { // KAKU Command eg.
|
||||
if (InputBuffer_Serial[15] != ';') return false;
|
||||
|
||||
InputBuffer_Serial[9]='0';
|
||||
InputBuffer_Serial[10]='x';
|
||||
InputBuffer_Serial[15]=0;
|
||||
unsigned int tempbyte1=0;
|
||||
tempbyte1=str2int(InputBuffer_Serial+9); // get parameter 1
|
||||
|
||||
int tempbyte2=0;
|
||||
InputBuffer_Serial[14]='0';
|
||||
InputBuffer_Serial[15]='x';
|
||||
InputBuffer_Serial[18]=0;
|
||||
tempbyte2=str2int(InputBuffer_Serial+14); // get parameter 2
|
||||
//-----------------------------------------------
|
||||
unsigned long bitstream1=tempbyte1; // address
|
||||
unsigned long bitstream=tempbyte2; // ringtone
|
||||
|
||||
RawSignal.Multiply=50;
|
||||
RawSignal.Repeats=20;
|
||||
RawSignal.Delay=3; // 1 = 900 3=2825 5= 6= x
|
||||
RawSignal.Pulses[1]=BYRONLOW/RawSignal.Multiply;
|
||||
//RawSignal.Pulses[1]=BYRONSTART/RawSignal.Multiply;
|
||||
for (byte x=17;x>=2;x=x-1) {
|
||||
if ((bitstream1 & 1) == 1)
|
||||
RawSignal.Pulses[x] = BYRONHIGH/RawSignal.Multiply;
|
||||
else
|
||||
RawSignal.Pulses[x] = BYRONLOW/RawSignal.Multiply;
|
||||
bitstream1 = bitstream1 >> 1;
|
||||
}
|
||||
for (byte x=25;x>=18;x=x-1) {
|
||||
if ((bitstream & 1) == 1)
|
||||
RawSignal.Pulses[x] = BYRONHIGH/RawSignal.Multiply;
|
||||
else
|
||||
RawSignal.Pulses[x] = BYRONLOW/RawSignal.Multiply;
|
||||
bitstream = bitstream >> 1;
|
||||
}
|
||||
//RawSignal.Pulses[26]=BYRONSTART/RawSignal.Multiply;
|
||||
RawSignal.Pulses[26]=BYRONSPACE/RawSignal.Multiply;
|
||||
RawSignal.Number=26;
|
||||
RawSendRF();
|
||||
RawSignal.Multiply=RAWSIGNAL_SAMPLE_RATE;
|
||||
success=true;
|
||||
//-----------------------------------------------
|
||||
}
|
||||
return success;
|
||||
}
|
||||
#endif // PLUGIN_TX_072
|
|
@ -0,0 +1,166 @@
|
|||
//#######################################################################################################
|
||||
//## This Plugin is only for use with the RFLink software package ##
|
||||
//## Plugin-073 Deltronic Doorbell ##
|
||||
//#######################################################################################################
|
||||
/*********************************************************************************************\
|
||||
* This Plugin takes care of reception And sending of the Deltronic doorbell
|
||||
*
|
||||
* Author : Stuntteam / Jonas Jespersen
|
||||
* 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!
|
||||
*********************************************************************************************
|
||||
* Technical information:
|
||||
*
|
||||
* The doorbell uses the UM3750 circuit which sends out a 12 bit signal:
|
||||
*
|
||||
* AAAAAAAA BBBB
|
||||
*
|
||||
* A = Always 1
|
||||
* B = Address (Can be either 1, 5 or 9)
|
||||
*
|
||||
* Address 1
|
||||
* 20;0D;DEBUG;Pulses=26;Pulses(uSec)=600,1150,525,1175,500,1175,475,1200,500,1175,500,1200,475,1175,475,1200,475,575,1075,575,1075,575,1075,1225,450;
|
||||
* 000000001110
|
||||
* Address 5
|
||||
* 20;17;DEBUG;Pulses=26;Pulses(uSec)=550,1075,425,1100,400,1125,425,1100,400,1125,400,1150,375,1125,400,1125,375,550,900,1125,375,550,900,1150,375;
|
||||
* 000000001010
|
||||
* Address 9
|
||||
* 20;1B;DEBUG;Pulses=26;Pulses(uSec)=600,1150,500,1175,525,1175,500,1175,500,1175,500,1175,500,1175,475,1200,500,1200,475,575,1075,600,1075,1200,475;
|
||||
* 000000000110
|
||||
\*********************************************************************************************/
|
||||
#define DELTRONIC_PULSECOUNT 26
|
||||
#define LENGTH_DEVIATION 300
|
||||
|
||||
#ifdef PLUGIN_073
|
||||
boolean Plugin_073(byte function, char *string) {
|
||||
if (RawSignal.Number != DELTRONIC_PULSECOUNT) return false;
|
||||
//==================================================================================
|
||||
unsigned long bitstream = 0L;
|
||||
unsigned long checksum = 0L;
|
||||
//==================================================================================
|
||||
if (RawSignal.Pulses[1]*RAWSIGNAL_SAMPLE_RATE > 675) return false; // First pulse is start bit and should be short!
|
||||
for(byte x=2;x < DELTRONIC_PULSECOUNT;x=x+2) {
|
||||
if (RawSignal.Pulses[x]*RAWSIGNAL_SAMPLE_RATE > 800) { // long pulse (800-1275)
|
||||
if (RawSignal.Pulses[x]*RAWSIGNAL_SAMPLE_RATE > 1275) return false; // pulse too long to be valid
|
||||
if (RawSignal.Pulses[x+1]*RAWSIGNAL_SAMPLE_RATE > 675) return false; // invalid manchestercode (10 01)
|
||||
bitstream = (bitstream << 1) | 0x1; // 10 => 1 bit
|
||||
} else { // short pulse
|
||||
if (RawSignal.Pulses[x]*RAWSIGNAL_SAMPLE_RATE < 250) return false; // too short
|
||||
if (RawSignal.Pulses[x+1]*RAWSIGNAL_SAMPLE_RATE < 700) return false; // invalid manchestercode (10 01)
|
||||
bitstream = bitstream << 1; // 01 => 0 bit
|
||||
}
|
||||
}
|
||||
//==================================================================================
|
||||
// Prevent repeating signals from showing up
|
||||
//==================================================================================
|
||||
if( (SignalHash!=SignalHashPrevious) || (RepeatingTimer+2000<millis()) ){
|
||||
// not seen the RF packet recently
|
||||
} else {
|
||||
// already seen the RF packet recently
|
||||
return true;
|
||||
}
|
||||
//==================================================================================
|
||||
// all bytes received, make sure checksum is okay
|
||||
//==================================================================================
|
||||
checksum = (bitstream) & 0x00000FF0L;
|
||||
if (checksum != 0x00000FF0L) { // First 8 bits should always be 1
|
||||
//Serial.println("crc error");
|
||||
return false;
|
||||
}
|
||||
if (bitstream == 0) return false; // sanity check
|
||||
//==================================================================================
|
||||
// Output
|
||||
// ----------------------------------
|
||||
Serial.print("20;");
|
||||
PrintHexByte(PKSequenceNumber++);
|
||||
Serial.print(F(";Deltronic;")); // Label
|
||||
// ----------------------------------
|
||||
sprintf(pbuffer, "ID=%04x;",(bitstream) & 0x0000000FL); // ID
|
||||
Serial.print( pbuffer );
|
||||
Serial.print(F("SWITCH=1;CMD=ON;"));
|
||||
Serial.print(F("CHIME=01;"));
|
||||
Serial.println();
|
||||
//==================================================================================
|
||||
RawSignal.Repeats=true; // suppress repeats of the same RF packet
|
||||
RawSignal.Number=0; // do not process the packet any further
|
||||
return true;
|
||||
}
|
||||
#endif // PLUGIN_073
|
||||
|
||||
#ifdef PLUGIN_TX_073
|
||||
void Deltronic_Send(unsigned long address);
|
||||
|
||||
boolean PluginTX_073(byte function, char *string) {
|
||||
boolean success=false;
|
||||
unsigned long bitstream=0L;
|
||||
//10;DELTRONIC;001c33;1;OFF;
|
||||
//012345678901234567890123456
|
||||
if (strncasecmp(InputBuffer_Serial+3,"DELTRONIC;",10) == 0) {
|
||||
InputBuffer_Serial[11]=0x30;
|
||||
InputBuffer_Serial[12]=0x78;
|
||||
InputBuffer_Serial[19]=0;
|
||||
bitstream=str2int(InputBuffer_Serial+11);
|
||||
bitstream = (bitstream) | 0x00000FF0L;
|
||||
Deltronic_Send(bitstream); // Send RF packet
|
||||
success=true;
|
||||
}
|
||||
return success;
|
||||
}
|
||||
|
||||
void Deltronic_Send(unsigned long address) {
|
||||
byte repeatTimes = 16;
|
||||
byte repeat, index;
|
||||
int periodLong, periodSync;
|
||||
unsigned long bitmask;
|
||||
int period = 640;
|
||||
|
||||
periodLong = 2 * period;
|
||||
periodSync = 36 * period;
|
||||
|
||||
digitalWrite(PIN_RF_RX_VCC,LOW); // Power off the RF receiver (if wired that way) to protect against interference
|
||||
digitalWrite(PIN_RF_TX_VCC,HIGH); // Enable 433Mhz transmitter
|
||||
delayMicroseconds(TRANSMITTER_STABLE_DELAY); // short delay to let the transmitter become stable (Note: Aurel RTX MID needs 500µS/0,5ms)
|
||||
|
||||
// Send seperator
|
||||
digitalWrite(PIN_RF_TX_DATA, HIGH);
|
||||
delayMicroseconds(period);
|
||||
|
||||
// Send sync
|
||||
digitalWrite(PIN_RF_TX_DATA, LOW);
|
||||
delayMicroseconds(periodSync);
|
||||
digitalWrite(PIN_RF_TX_DATA, HIGH);
|
||||
delayMicroseconds(period);
|
||||
|
||||
for(repeat = 0; repeat < repeatTimes; repeat++) {
|
||||
bitmask = 0x00000800L;
|
||||
for (index = 0; index < 12; index++) {
|
||||
if (address & bitmask) {
|
||||
// Send 1
|
||||
digitalWrite(PIN_RF_TX_DATA, LOW);
|
||||
delayMicroseconds(periodLong);
|
||||
digitalWrite(PIN_RF_TX_DATA, HIGH);
|
||||
delayMicroseconds(period);
|
||||
} else {
|
||||
// Send 0
|
||||
digitalWrite(PIN_RF_TX_DATA, LOW);
|
||||
delayMicroseconds(period);
|
||||
digitalWrite(PIN_RF_TX_DATA, HIGH);
|
||||
delayMicroseconds(periodLong);
|
||||
}
|
||||
bitmask >>= 1;
|
||||
}
|
||||
// Send sync
|
||||
digitalWrite(PIN_RF_TX_DATA, LOW);
|
||||
delayMicroseconds(periodSync);
|
||||
digitalWrite(PIN_RF_TX_DATA, HIGH);
|
||||
delayMicroseconds(period);
|
||||
}
|
||||
|
||||
digitalWrite(PIN_RF_TX_DATA, LOW);
|
||||
delayMicroseconds(TRANSMITTER_STABLE_DELAY); // short delay to let the transmitter become stable (Note: Aurel RTX MID needs 500µS/0,5ms)
|
||||
digitalWrite(PIN_RF_TX_VCC,LOW); // Disable the 433Mhz transmitter
|
||||
digitalWrite(PIN_RF_RX_VCC,HIGH); // Enable the 433Mhz receiver
|
||||
RFLinkHW();
|
||||
}
|
||||
#endif // PLUGIN_TX_073
|
|
@ -0,0 +1,192 @@
|
|||
//#######################################################################################################
|
||||
//## This Plugin is only for use with the RFLink software package ##
|
||||
//## Plugin-74: RL-02 Digital Doorbell ##
|
||||
//#######################################################################################################
|
||||
/*********************************************************************************************\
|
||||
* This plugin takes care of sending and receiving the RL-02 Digital Doorbell protocol.
|
||||
*
|
||||
* Author : Jonas Jespersen
|
||||
* 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!
|
||||
***********************************************************************************************
|
||||
* Technical information:
|
||||
*
|
||||
* The RL-02 Digital Doorbell uses a protocol similar to PT2262 which send 12 bits that can be either
|
||||
* 1, 0 or f (float).
|
||||
*
|
||||
* The doorbell transmitter has 2 buttons; One for ringing the doorbell and a button inside the transmitter
|
||||
* for changing the chime. Everytime the change chime button is pressed the doorbell toggles through a number
|
||||
* of available chimes, and when ring button is pressed the chime last selected with the change chime button
|
||||
* will sound.
|
||||
*
|
||||
* AAAAAAAAAAA B
|
||||
*
|
||||
* A = Always f0ff0f0ffff
|
||||
* B = f or 1 (f = Change chime button, 1 = Ring button)
|
||||
*
|
||||
* Ring:
|
||||
* 20;6D;DEBUG;Pulses=50;Pulses(uSec)=175,400,450,50,100,400,100,400,100,400,450,50,100,400,450,50,100,425,100,400,100,400,450,50,100,400,100,400,100,400,450,50,100,400,425,75,100,400,425,75,100,400,450,75,425,75,425,75,75;
|
||||
*
|
||||
* Change chime:
|
||||
* 20;0B;DEBUG;Pulses=50;Pulses(uSec)=175,400,450,50,100,400,100,400,100,400,450,50,100,400,450,50,100,400,100,400,100,400,425,50,100,400,100,400,100,400,450,50,100,400,425,50,100,400,425,50,100,400,425,75,100,400,425,75,100;
|
||||
\*********************************************************************************************/
|
||||
#define RL02_CodeLength 12
|
||||
#define RL02_T 125 // 175 uS
|
||||
|
||||
#ifdef PLUGIN_074
|
||||
boolean Plugin_074(byte function, char *string) {
|
||||
if (RawSignal.Number != (RL02_CodeLength * 4) + 2) return false;
|
||||
|
||||
unsigned long bitstream = 0L;
|
||||
unsigned long checksum = 0L;
|
||||
int i, j;
|
||||
boolean error = false;
|
||||
// ==========================================================================
|
||||
for (i = 0; i < RL02_CodeLength; i++) {
|
||||
j = (RL02_T * 2) / RAWSIGNAL_SAMPLE_RATE;
|
||||
|
||||
if (RawSignal.Pulses[4 * i + 1] < j && RawSignal.Pulses[4 * i + 2] > j && RawSignal.Pulses[4 * i + 3] < j && RawSignal.Pulses[4 * i + 4] > j) { // 0101
|
||||
bitstream = (bitstream >> 1); // 0
|
||||
} else
|
||||
if (RawSignal.Pulses[4 * i + 1] < j && RawSignal.Pulses[4 * i + 2] > j && RawSignal.Pulses[4 * i + 3] > j && RawSignal.Pulses[4 * i + 4] < j) { // 0110
|
||||
bitstream = (bitstream >> 1 | (1 << (RL02_CodeLength - 1))); // float
|
||||
} else
|
||||
if (RawSignal.Pulses[4 * i + 1] > j && RawSignal.Pulses[4 * i + 2] < j && RawSignal.Pulses[4 * i + 3] > j && RawSignal.Pulses[4 * i + 4] < j) { // 1010
|
||||
bitstream = (bitstream >> 1); // 1
|
||||
} else {
|
||||
if (i == 0) {
|
||||
if (RawSignal.Pulses[4 * i + 1] > j && RawSignal.Pulses[4 * i + 2] > j && RawSignal.Pulses[4 * i + 3] < j && RawSignal.Pulses[4 * i + 4] > j) { // 1101
|
||||
bitstream = (bitstream >> 1 | (1 << (RL02_CodeLength - 1))); // 1
|
||||
} else {
|
||||
error = true;
|
||||
}
|
||||
} else {
|
||||
error = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
// ==========================================================================
|
||||
// all bytes received, make sure packet is valid and checksum is okay
|
||||
// ==========================================================================
|
||||
if (error == true) return false;
|
||||
if (bitstream == 0) return false; // sanity check
|
||||
checksum = (bitstream) & 0x000007FFL;
|
||||
if (checksum != 0x000007ADL) return false;
|
||||
if (bitstream == 0) return false; // sanity check
|
||||
// ==========================================================================
|
||||
// ----------------------------------
|
||||
// Output
|
||||
// ----------------------------------
|
||||
Serial.print("20;");
|
||||
PrintHexByte(PKSequenceNumber++);
|
||||
Serial.print(F(";Byron MP;")); // Label
|
||||
// ----------------------------------
|
||||
sprintf(pbuffer, "ID=%04x;", (bitstream & 0x00000800L) ? 1 : 0); // ID: 0 = Ring button, 1 = Change chime button
|
||||
Serial.print( pbuffer );
|
||||
Serial.print(F("SWITCH=1;CMD=ON;"));
|
||||
Serial.print(F("CHIME=01;"));
|
||||
Serial.println();
|
||||
// ----------------------------------
|
||||
RawSignal.Repeats=true;
|
||||
RawSignal.Number=0;
|
||||
return true;
|
||||
}
|
||||
#endif //PLUGIN_074
|
||||
|
||||
#ifdef PLUGIN_TX_074
|
||||
void RL02_Send(unsigned long address);
|
||||
|
||||
boolean PluginTX_074(byte function, char *string) {
|
||||
boolean success=false;
|
||||
unsigned long bitstream=0;
|
||||
//10;Byron MP;001c33;1;OFF;
|
||||
//012345678901234567890123456
|
||||
if (strncasecmp(InputBuffer_Serial+3,"BYRON MP;",9) == 0) {
|
||||
InputBuffer_Serial[10]=0x30;
|
||||
InputBuffer_Serial[11]=0x78;
|
||||
InputBuffer_Serial[18]=0;
|
||||
bitstream=str2int(InputBuffer_Serial+10);
|
||||
bitstream = ((bitstream) << 11) | 0x000007ADL;
|
||||
RL02_Send(bitstream); // Send RF packet
|
||||
success=true;
|
||||
}
|
||||
return success;
|
||||
}
|
||||
|
||||
void RL02_Send(unsigned long address) {
|
||||
int fpulse = 175; // Pulse witdh in microseconds
|
||||
int fretrans = 7; // Number of code retransmissions
|
||||
uint32_t fdatabit;
|
||||
uint32_t fdatamask = 0x00000001;
|
||||
uint32_t fsendbuff;
|
||||
|
||||
digitalWrite(PIN_RF_RX_VCC,LOW); // Turn off power to the RF receiver
|
||||
digitalWrite(PIN_RF_TX_VCC,HIGH); // Enable the 433Mhz transmitter
|
||||
delayMicroseconds(TRANSMITTER_STABLE_DELAY); // short delay to let the transmitter become stable (Note: Aurel RTX MID needs 500µS/0,5ms)
|
||||
|
||||
for (int nRepeat = 0; nRepeat <= fretrans; nRepeat++) {
|
||||
fsendbuff = address;
|
||||
// Send command
|
||||
|
||||
for (int i = 0; i < 11; i++) { // RL-02 packet is 12 bits
|
||||
// read data bit
|
||||
fdatabit = fsendbuff & fdatamask; // Get most right bit
|
||||
fsendbuff = (fsendbuff >> 1); // Shift right
|
||||
|
||||
// PT2262 data can be 0, 1 or float.
|
||||
if (fdatabit != fdatamask) { // Write 0
|
||||
digitalWrite(PIN_RF_TX_DATA, HIGH);
|
||||
delayMicroseconds(fpulse);
|
||||
digitalWrite(PIN_RF_TX_DATA, LOW);
|
||||
delayMicroseconds(fpulse * 3);
|
||||
digitalWrite(PIN_RF_TX_DATA, HIGH);
|
||||
delayMicroseconds(fpulse);
|
||||
digitalWrite(PIN_RF_TX_DATA, LOW);
|
||||
delayMicroseconds(fpulse * 3);
|
||||
} else { // Write float
|
||||
digitalWrite(PIN_RF_TX_DATA, HIGH);
|
||||
delayMicroseconds(fpulse * 1);
|
||||
digitalWrite(PIN_RF_TX_DATA, LOW);
|
||||
delayMicroseconds(fpulse * 3);
|
||||
digitalWrite(PIN_RF_TX_DATA, HIGH);
|
||||
delayMicroseconds(fpulse * 3);
|
||||
digitalWrite(PIN_RF_TX_DATA, LOW);
|
||||
delayMicroseconds(fpulse * 1);
|
||||
}
|
||||
}
|
||||
|
||||
fdatabit = fsendbuff & fdatamask; // Get most right bit
|
||||
// Send last bit. Can be either 1 or float
|
||||
if (fdatabit != fdatamask) { // Write 1
|
||||
digitalWrite(PIN_RF_TX_DATA, HIGH);
|
||||
delayMicroseconds(fpulse * 3);
|
||||
digitalWrite(PIN_RF_TX_DATA, LOW);
|
||||
delayMicroseconds(fpulse);
|
||||
digitalWrite(PIN_RF_TX_DATA, HIGH);
|
||||
delayMicroseconds(fpulse * 3);
|
||||
digitalWrite(PIN_RF_TX_DATA, LOW);
|
||||
delayMicroseconds(fpulse);
|
||||
} else { // Write float
|
||||
digitalWrite(PIN_RF_TX_DATA, HIGH);
|
||||
delayMicroseconds(fpulse * 1);
|
||||
digitalWrite(PIN_RF_TX_DATA, LOW);
|
||||
delayMicroseconds(fpulse * 3);
|
||||
digitalWrite(PIN_RF_TX_DATA, HIGH);
|
||||
delayMicroseconds(fpulse * 3);
|
||||
digitalWrite(PIN_RF_TX_DATA, LOW);
|
||||
delayMicroseconds(fpulse * 1);
|
||||
}
|
||||
|
||||
// Send sync bit
|
||||
digitalWrite(PIN_RF_TX_DATA, HIGH);
|
||||
delayMicroseconds(fpulse * 1);
|
||||
digitalWrite(PIN_RF_TX_DATA, LOW); // and lower the signal
|
||||
delayMicroseconds(fpulse * 31);
|
||||
}
|
||||
delayMicroseconds(TRANSMITTER_STABLE_DELAY); // short delay to let the transmitter become stable (Note: Aurel RTX MID needs 500µS/0,5ms)
|
||||
digitalWrite(PIN_RF_TX_VCC,LOW); // Turn thew 433Mhz transmitter off
|
||||
digitalWrite(PIN_RF_RX_VCC,HIGH); // Turn the 433Mhz receiver on
|
||||
RFLinkHW();
|
||||
}
|
||||
#endif // PLUGIN_TX_074
|
|
@ -0,0 +1,143 @@
|
|||
//#######################################################################################################
|
||||
//## This Plugin is only for use with the RFLink software package ##
|
||||
//## Plugin-75 Lidl doorbell ##
|
||||
//#######################################################################################################
|
||||
/*********************************************************************************************\
|
||||
* This plugin takes care of decoding the Lidl/SilverCrest Doorbell protocol for model Z31370-TX
|
||||
*
|
||||
* Author : StuntTeam
|
||||
* Support : www.nodo-domotica.nl
|
||||
* Date : 9-02-2015
|
||||
* Version : 1.0
|
||||
* Compatibility : RFLink 1.0
|
||||
* 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!
|
||||
*********************************************************************************************
|
||||
* Changelog: v1.0 initial release
|
||||
*********************************************************************************************
|
||||
* Technical Information:
|
||||
* Decodes signals from a Lidl Doorbell, (90 pulses, 40 bits, 433 MHz).
|
||||
* Lidl Doorbell Message Format:
|
||||
* 1010 1111 1000 0010 0001 1011 0011 0000 0000 0000 AF821B3000
|
||||
* -------------- always zero
|
||||
*
|
||||
* Sample packet: (Nodo Pulse timing)
|
||||
* 1850,1200,1400,1200,1400,1200,1400,1200,1400, (Preamble)
|
||||
* 700,400,200,900,700,400,200,900,700,400,700,400,700,400,700,400,700,400,200,900,200,900,200,900,200,900,200,900,700,400,250,900,200,900,200,900,700,
|
||||
* 400,700,400,700,400,200,900,700,400,700,400,200,900,200,900,700,400,700,400,200,900,200,900,200,900,200,900,200,900,200,900,200,900,200,900,200,900,
|
||||
* 200,900,200,900,250,900,200
|
||||
*********************************************************************************************
|
||||
* Technical Information:
|
||||
* Decodes signals from a Lidl SilverCrest Z31370-TX Doorbell, (114 pulses, 48 bits, 433 MHz).
|
||||
* SilverCrest Doorbell Message Format:
|
||||
* 01011100 10100101 10001000 | 00000100 11010110 10111011 10010111 5CA588 04D6BB97
|
||||
* always the same | device unique number
|
||||
*
|
||||
* Sample packet:
|
||||
* 20;14;DEBUG;Pulses=114;Pulses(uSec)=360,60,60,390,360,60,60,390,60,390,60,390,390,60,360,60,60,390,360,60,60,390,360,60,360,60,60,390,360,60,60,390,60,390,360,60,360,60,360,60,30,390,360,60,360,60,360,60,390,60,360,60,60,390,390,60,360,60,360,60,390,60,360,60,390,60,360,60,360,60,390,60,60,390,60,390,30,390,60,390,60,390,360,60,60,390,60,390,60,390,60,390,360,60,360,60,60,390,60,390,60,390,360,60,60,390,60,390,360,60,60,390,360,1260;
|
||||
\*********************************************************************************************/
|
||||
// ==================================================================================
|
||||
#define LIDL_PULSECOUNT 90 // type 0
|
||||
#define LIDL_PULSECOUNT2 114 // type 1
|
||||
#define PLUGIN_ID 75
|
||||
|
||||
#ifdef PLUGIN_075
|
||||
boolean Plugin_075(byte function, char *string) {
|
||||
if ((RawSignal.Number != LIDL_PULSECOUNT) && (RawSignal.Number != LIDL_PULSECOUNT2)) return false;
|
||||
unsigned long bitstream=0;
|
||||
unsigned long bitstream2=0;
|
||||
|
||||
int bitcount=0;
|
||||
byte type=0;
|
||||
//==================================================================================
|
||||
// get all bits
|
||||
if (RawSignal.Number == LIDL_PULSECOUNT) {
|
||||
if (RawSignal.Pulses[1]*RawSignal.Multiply > 1000 && RawSignal.Pulses[2]*RawSignal.Multiply > 1000 &&
|
||||
RawSignal.Pulses[3]*RawSignal.Multiply > 1000 && RawSignal.Pulses[4]*RawSignal.Multiply > 1000 &&
|
||||
RawSignal.Pulses[5]*RawSignal.Multiply > 1000 && RawSignal.Pulses[6]*RawSignal.Multiply > 1000 &&
|
||||
RawSignal.Pulses[7]*RawSignal.Multiply > 1000 && RawSignal.Pulses[8]*RawSignal.Multiply > 1000 && RawSignal.Pulses[9]*RawSignal.Multiply > 1000 ) {
|
||||
//
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
for(int x=10;x <=90;x+=2) {
|
||||
if (bitcount < 28){
|
||||
if (RawSignal.Pulses[x]*RawSignal.Multiply > 550) {
|
||||
bitstream = (bitstream << 1);
|
||||
bitcount++;
|
||||
} else {
|
||||
bitstream = (bitstream << 1) | 0x1;
|
||||
bitcount++;
|
||||
}
|
||||
} else {
|
||||
if (RawSignal.Pulses[x]*RawSignal.Multiply > 550) {
|
||||
bitstream2 = (bitstream2 << 1);
|
||||
bitcount++;
|
||||
} else {
|
||||
bitstream2 = (bitstream2 << 1) | 0x1;
|
||||
bitcount++;
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if (RawSignal.Pulses[0] != PLUGIN_ID) return false; // only accept plugin1 translated packets
|
||||
type=1;
|
||||
for(byte x=1;x < LIDL_PULSECOUNT2-1;x+=2) {
|
||||
if (RawSignal.Pulses[x]*RawSignal.Multiply > 200) {
|
||||
if (RawSignal.Pulses[x+1]*RawSignal.Multiply > 200) return false; // invalid pulse length
|
||||
if (bitcount > 23) {
|
||||
bitstream2 = (bitstream2 << 1);
|
||||
} else {
|
||||
bitstream = (bitstream << 1);
|
||||
}
|
||||
bitcount++;
|
||||
} else {
|
||||
if (RawSignal.Pulses[x+1]*RawSignal.Multiply < 200) return false; // invalid pulse length
|
||||
if (bitcount > 23) {
|
||||
bitstream2 = (bitstream2 << 1) | 0x1;
|
||||
} else {
|
||||
bitstream = (bitstream << 1) | 0x1;
|
||||
}
|
||||
bitcount++;
|
||||
}
|
||||
}
|
||||
}
|
||||
//==================================================================================
|
||||
// all bytes received, make sure checksum is okay
|
||||
//==================================================================================
|
||||
if (type==0) {
|
||||
if ((bitstream2 &0xfff) != 0x00) return false; // these 8 bits are always 0
|
||||
} else {
|
||||
if (bitstream != 0x5ca588) return false;
|
||||
}
|
||||
//==================================================================================
|
||||
// Prevent repeating signals from showing up
|
||||
//==================================================================================
|
||||
if((SignalHash!=SignalHashPrevious) || ((RepeatingTimer+2000)<millis()) || (SignalCRC != bitstream) ) {
|
||||
SignalCRC=bitstream; // not seen the RF packet recently
|
||||
} else {
|
||||
return true; // already seen the RF packet recently
|
||||
}
|
||||
//==================================================================================
|
||||
// Output
|
||||
// ----------------------------------
|
||||
Serial.print("20;");
|
||||
PrintHexByte(PKSequenceNumber++);
|
||||
// ----------------------------------
|
||||
if (type == 0) {
|
||||
Serial.print(";SilverCrest;"); // Label
|
||||
sprintf(pbuffer, "ID=%08lx;", bitstream); // ID
|
||||
} else {
|
||||
Serial.print(";SilverCrest;"); // Label
|
||||
sprintf(pbuffer, "ID=%08lx;", bitstream2); // ID
|
||||
}
|
||||
Serial.print( pbuffer );
|
||||
Serial.print(F("SWITCH=1;CMD=ON;"));
|
||||
Serial.print(F("CHIME=01;"));
|
||||
Serial.println();
|
||||
//==================================================================================
|
||||
RawSignal.Repeats=true; // suppress repeats of the same RF packet
|
||||
RawSignal.Number=0; // do not process the packet any further
|
||||
return true;
|
||||
}
|
||||
#endif // PLUGIN_075_CORE
|
|
@ -0,0 +1,119 @@
|
|||
//#######################################################################################################
|
||||
//## This Plugin is only for use with the RFLink software package ##
|
||||
//## Plugin-80 Flamingo FA20RF Rookmelder ##
|
||||
//#######################################################################################################
|
||||
/*********************************************************************************************\
|
||||
* Dit protocol zorgt voor ontvangst van Flamingo FA20RF rookmelder
|
||||
*
|
||||
* Author : StuntTeam
|
||||
* 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!
|
||||
*********************************************************************************************
|
||||
* Changelog: v1.0 initial release
|
||||
*********************************************************************************************
|
||||
* Technical information:
|
||||
* The Flamingo FA20RF/FA21RF Smokedetector contains both a RF receiver and transmitter.
|
||||
* Every unit has a unique ID. The detector has a "learn" button to learn the ID of other units.
|
||||
* That is what links the units to each other. After linking multiple units, they all have the same ID!
|
||||
* Normally, one unit is used as master and the code of the master is learned to the slaves
|
||||
*
|
||||
* Attention: The smoke detector gives an alarm as long as the message is transmitted
|
||||
*
|
||||
* Sample:
|
||||
* 20;32;DEBUG;Pulses=52;Pulses(uSec)=2500,800,650,1250,650,1250,650,1250,650,1250,650,1250,650,1275,650,1250,650,2550,650,1275,650,2550,650,1250,650,1250,650,2550,650,2550,650,1275,650,2550,
|
||||
* 650,2550,650,1275,650,2550,650,2550,650,1275,650,1275,650,2550,650,1200,650;
|
||||
* 000000010100110110110010 = 014DB2
|
||||
* 20;0C;DEBUG;Pulses=52;Pulses(uSec)=2500,825,625,2575,625,1275,625,1300,625,2575,625,1275,625,2575,625,2575,625,2575,625,2575,625,2575,625,2575,625,1275,625,1275,625,1275,625,2575,625,2575,
|
||||
* 625,2575,625,1275,625,2575,625,2575,625,1300,625,1275,625,2575,625,1225,625;
|
||||
* 100101111110001110110010 = 97E3B2
|
||||
* 20;0D;FA20RF;ID=97e3b2;SMOKEALERT=ON;
|
||||
*
|
||||
* False positive:
|
||||
* 20;52;DEBUG;Pulses=52;Pulses(uSec)=420,1860,330,3810,360,3960,360,1950,390,1920,360,3960,360,3960,360,3960,390,3960,390,3960,390,3960,390,1920,390,1920,390,1920,390,1890,480,1800,390,3930,390,1920,390,1920,420,1920,390,1920,420,1890,450,1860,420,1890,390,3930,390,6990;
|
||||
\*********************************************************************************************/
|
||||
#define FA20RFSTART 3000 // 8000
|
||||
#define FA20RFSPACE 675 // 800
|
||||
#define FA20RFLOW 1250 // 1300
|
||||
#define FA20RFHIGH 2550 // 2600
|
||||
#define FA20_PULSECOUNT 52
|
||||
|
||||
#ifdef PLUGIN_080
|
||||
boolean Plugin_080(byte function, char *string) {
|
||||
if (RawSignal.Number != FA20_PULSECOUNT) return false;
|
||||
unsigned long bitstream=0L;
|
||||
//==================================================================================
|
||||
for(byte x=4;x<=FA20_PULSECOUNT-2;x=x+2) {
|
||||
if (RawSignal.Pulses[x-1]*RAWSIGNAL_SAMPLE_RATE > 1000) return false; // every preceding pulse must be below 1000!
|
||||
if (RawSignal.Pulses[x]*RAWSIGNAL_SAMPLE_RATE > 2000) { // long pulse
|
||||
if (RawSignal.Pulses[x]*RAWSIGNAL_SAMPLE_RATE > 2800) return false; // long pulse too long
|
||||
bitstream = (bitstream << 1) | 0x1;
|
||||
} else {
|
||||
if (RawSignal.Pulses[x]*RAWSIGNAL_SAMPLE_RATE > 1500) return false; // short pulse too long
|
||||
if (RawSignal.Pulses[x]*RAWSIGNAL_SAMPLE_RATE < 1000) return false; // short pulse too short
|
||||
bitstream = bitstream << 1;
|
||||
}
|
||||
}
|
||||
//==================================================================================
|
||||
if (bitstream == 0) return false;
|
||||
if (bitstream == 0xFFFFFF) return false;
|
||||
if (((bitstream)&0xffff) == 0xffff) return false;
|
||||
//==================================================================================
|
||||
// Output
|
||||
// ----------------------------------
|
||||
sprintf(pbuffer, "20;%02X;", PKSequenceNumber++);// Node and packet number
|
||||
Serial.print( pbuffer );
|
||||
// ----------------------------------
|
||||
Serial.print(F("FA20RF;")); // Label
|
||||
sprintf(pbuffer, "ID=%06lx;", bitstream ); // ID
|
||||
Serial.print( pbuffer );
|
||||
Serial.print(F("SMOKEALERT=ON;"));
|
||||
Serial.println();
|
||||
//==================================================================================
|
||||
RawSignal.Repeats=true; // suppress repeats of the same RF packet
|
||||
RawSignal.Number=0; // do not process the packet any further
|
||||
return true;
|
||||
}
|
||||
#endif // PLUGIN_080
|
||||
|
||||
#ifdef PLUGIN_TX_080
|
||||
boolean PluginTX_080(byte function, char *string) {
|
||||
boolean success=false;
|
||||
//10;FA20RF;67f570;1;ON;
|
||||
//012345678901234567890
|
||||
unsigned long bitstream=0;
|
||||
if (strncasecmp(InputBuffer_Serial+3,"FA20RF;",7) == 0) { // KAKU Command eg.
|
||||
if (InputBuffer_Serial[18] != ';') return false;
|
||||
InputBuffer_Serial[8]=0x30;
|
||||
InputBuffer_Serial[9]=0x78;
|
||||
InputBuffer_Serial[16]=0;
|
||||
bitstream=str2int(InputBuffer_Serial+8);
|
||||
byte cmd=str2cmd(InputBuffer_Serial+19); // ON/OFF
|
||||
if (cmd!=VALUE_ON) return true; // pretend command was ok but we dont have to send anything..
|
||||
// ---------- SMOKEALERT SEND -----------
|
||||
RawSignal.Multiply=50;
|
||||
RawSignal.Repeats=10;
|
||||
RawSignal.Delay=20;
|
||||
RawSignal.Pulses[1]=FA20RFSTART/RawSignal.Multiply;
|
||||
//RawSignal.Pulses[2]=FA20RFSPACE/RawSignal.Multiply;
|
||||
//RawSignal.Pulses[3]=FA20RFSPACE/RawSignal.Multiply;
|
||||
RawSignal.Pulses[2]=(FA20RFSPACE+125)/RawSignal.Multiply;
|
||||
RawSignal.Pulses[3]=(FA20RFSPACE+25)/RawSignal.Multiply;
|
||||
for(byte x=49;x>=3;x=x-2) {
|
||||
RawSignal.Pulses[x]=FA20RFSPACE/RawSignal.Multiply;
|
||||
if ((bitstream & 1) == 1)
|
||||
RawSignal.Pulses[x+1] = FA20RFHIGH/RawSignal.Multiply;
|
||||
else
|
||||
RawSignal.Pulses[x+1] = FA20RFLOW/RawSignal.Multiply;
|
||||
bitstream = bitstream >> 1;
|
||||
}
|
||||
RawSignal.Pulses[51]=FA20RFSPACE/RawSignal.Multiply;
|
||||
RawSignal.Pulses[52]=0;
|
||||
RawSignal.Number=52;
|
||||
RawSendRF();
|
||||
RawSignal.Multiply=RAWSIGNAL_SAMPLE_RATE; // restore setting
|
||||
success=true;
|
||||
}
|
||||
return success;
|
||||
}
|
||||
#endif // PLUGIN_080
|
|
@ -0,0 +1,177 @@
|
|||
//#######################################################################################################
|
||||
//## This Plugin is only for use with the RFLink software package ##
|
||||
//## Plugin-082 Mertik Maxitrol ##
|
||||
//#######################################################################################################
|
||||
/*********************************************************************************************\
|
||||
* This Plugin takes care of reception of Mertik Maxitrol / DRU for fireplaces
|
||||
* PCB markings: G6R H4TB / G6R 4HT.
|
||||
*
|
||||
* Author : StuntTeam
|
||||
* 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!
|
||||
*********************************************************************************************
|
||||
* Changelog: v1.0 initial release
|
||||
*********************************************************************************************
|
||||
* Technical information:
|
||||
*
|
||||
* 0001100101101001011001101
|
||||
* ----------------------- data bits (10=1 01=0)
|
||||
* -- preamble, always 00?
|
||||
* Shortened: (10=1 01=0)
|
||||
* 01100101101001011001101
|
||||
* 0 1 0 0 1 1 0 0 1 0 1 1
|
||||
*
|
||||
* 010011001011
|
||||
* ---- command => 4 bits
|
||||
* -------- address => 8 bits
|
||||
*
|
||||
* command bits:
|
||||
* 0111 7 off
|
||||
* 0011 3 on
|
||||
* 1011 b up
|
||||
* 1101 d down
|
||||
* 1000 8 stop
|
||||
* 1010 a go up
|
||||
* 1100 c go down
|
||||
*
|
||||
* Sample RF packet:
|
||||
* Pulses=26;Pulses(uSec)=475,300,325,700,325,700,325,700,325,700,725,300,725,300,725,300,725,300,725,300,325,700,725,300,725;
|
||||
\*********************************************************************************************/
|
||||
#define MAXITROL_PULSECOUNT 46
|
||||
|
||||
#define PLUGIN_081_RFSTART 100
|
||||
#define PLUGIN_081_RFSPACE 250
|
||||
#define PLUGIN_081_RFLOW 400
|
||||
#define PLUGIN_081_RFHIGH 750
|
||||
|
||||
#ifdef PLUGIN_081
|
||||
boolean Plugin_081(byte function, char *string) {
|
||||
if (RawSignal.Number !=MAXITROL_PULSECOUNT) return false;
|
||||
unsigned int bitstream=0L;
|
||||
byte address=0;
|
||||
byte command=0;
|
||||
byte status=0;
|
||||
//==================================================================================
|
||||
// get bits
|
||||
for(int x=3;x <= MAXITROL_PULSECOUNT-1;x=x+2) {
|
||||
if (RawSignal.Pulses[x]*RAWSIGNAL_SAMPLE_RATE < 550) {
|
||||
if (RawSignal.Pulses[x+1]*RAWSIGNAL_SAMPLE_RATE < 550) return false;
|
||||
bitstream = (bitstream << 1); // 0
|
||||
} else {
|
||||
if (RawSignal.Pulses[x]*RAWSIGNAL_SAMPLE_RATE > 900) return false;
|
||||
if (RawSignal.Pulses[x+1]*RAWSIGNAL_SAMPLE_RATE > 550) return false;
|
||||
bitstream = (bitstream << 1) | 0x1; // 1
|
||||
}
|
||||
}
|
||||
//==================================================================================
|
||||
// all bytes received, make sure packet is valid
|
||||
if (RawSignal.Pulses[1]*RAWSIGNAL_SAMPLE_RATE > 550) return false;
|
||||
if (RawSignal.Pulses[2]*RAWSIGNAL_SAMPLE_RATE > 550) return false;
|
||||
//==================================================================================
|
||||
// Prevent repeating signals from showing up
|
||||
//==================================================================================
|
||||
if( (SignalHash!=SignalHashPrevious) || (RepeatingTimer<millis()) ) {
|
||||
// not seen the RF packet recently
|
||||
if (bitstream == 0) return false; // sanity check
|
||||
} else {
|
||||
// already seen the RF packet recently
|
||||
return true;
|
||||
}
|
||||
//==================================================================================
|
||||
command=(bitstream) & 0x0f; // get address from pulses
|
||||
address=((bitstream)>>4)&0xff;
|
||||
if (command == 0xB) status=1; // up
|
||||
else if (command == 0xD) status=2; // down
|
||||
else if (command == 0x7) status=3; // off
|
||||
else if (command == 0x3) status=4; // on
|
||||
else if (command == 0x8) status=5; // stop
|
||||
else if (command == 0xa) status=6; // go up
|
||||
else if (command == 0xc) status=7; // go down
|
||||
else {
|
||||
return false;
|
||||
}
|
||||
//==================================================================================
|
||||
// Output
|
||||
// ----------------------------------
|
||||
sprintf(pbuffer, "20;%02X;", PKSequenceNumber++); // Node and packet number
|
||||
Serial.print( pbuffer );
|
||||
Serial.print(F("Mertik;")); // Label
|
||||
sprintf(pbuffer, "ID=%02x;", address); // ID
|
||||
Serial.print( pbuffer );
|
||||
sprintf(pbuffer, "SWITCH=%02x;", status);
|
||||
Serial.print( pbuffer );
|
||||
Serial.print(F("CMD="));
|
||||
if (status==1) Serial.print(F("UP;"));
|
||||
if (status==2) Serial.print(F("DOWN;"));
|
||||
if (status==3) Serial.print(F("OFF;"));
|
||||
if (status==4) Serial.print(F("ON;"));
|
||||
if (status==5) Serial.print(F("STOP;"));
|
||||
if (status==6) Serial.print(F("GOUP;"));
|
||||
if (status==7) Serial.print(F("GODOWN;"));
|
||||
Serial.println();
|
||||
//==================================================================================
|
||||
RawSignal.Repeats=true; // suppress repeats of the same RF packet
|
||||
RawSignal.Number=0;
|
||||
return true;
|
||||
}
|
||||
#endif // PLUGIN_081
|
||||
|
||||
#ifdef PLUGIN_TX_081
|
||||
boolean PluginTX_081(byte function, char *string) {
|
||||
boolean success=false;
|
||||
unsigned long bitstream=0L;
|
||||
//10;MERTIK;64;UP;
|
||||
//0123456789012345
|
||||
if (strncasecmp(InputBuffer_Serial+3,"MERTIK;",7) == 0) { // KAKU Command eg.
|
||||
if (InputBuffer_Serial[12] != ';') return false;
|
||||
unsigned int bitstream2=0; // holds last 8 bits
|
||||
|
||||
InputBuffer_Serial[8]=0x30;
|
||||
InputBuffer_Serial[9]=0x78; // Get address from hexadecimal value
|
||||
InputBuffer_Serial[12]=0x00; // Get address from hexadecimal value
|
||||
bitstream=str2int(InputBuffer_Serial+8); // Address (first 16 bits)
|
||||
|
||||
if(strcasecmp(InputBuffer_Serial+13,"stop")==0) bitstream2=0x8;
|
||||
else if(strcasecmp(InputBuffer_Serial+13,"on")==0) bitstream2=0x3;
|
||||
else if(strcasecmp(InputBuffer_Serial+13,"off")==0) bitstream2=0x7;
|
||||
else if(strcasecmp(InputBuffer_Serial+13,"up")==0) bitstream2=0xB;
|
||||
else if(strcasecmp(InputBuffer_Serial+13,"down")==0) bitstream2=0xD;
|
||||
else if(strcasecmp(InputBuffer_Serial+13,"go_up")==0) bitstream2=0xA;
|
||||
else if(strcasecmp(InputBuffer_Serial+13,"go_down")==0) bitstream2=0xC;
|
||||
if (bitstream2==0) return false;
|
||||
//-----------------------------------------------
|
||||
RawSignal.Multiply=50;
|
||||
RawSignal.Repeats=10;
|
||||
RawSignal.Delay=20;
|
||||
RawSignal.Pulses[1]=PLUGIN_081_RFLOW/RawSignal.Multiply;
|
||||
RawSignal.Pulses[2]=PLUGIN_081_RFLOW/RawSignal.Multiply;
|
||||
for(byte x=18;x>=3;x=x-2) {
|
||||
if ((bitstream & 1) == 1) {
|
||||
RawSignal.Pulses[x] = PLUGIN_081_RFLOW/RawSignal.Multiply;
|
||||
RawSignal.Pulses[x-1] = PLUGIN_081_RFHIGH /RawSignal.Multiply;
|
||||
} else {
|
||||
RawSignal.Pulses[x] = PLUGIN_081_RFHIGH /RawSignal.Multiply;
|
||||
RawSignal.Pulses[x-1] = PLUGIN_081_RFLOW/RawSignal.Multiply;
|
||||
}
|
||||
bitstream = bitstream >> 1;
|
||||
}
|
||||
for(byte x=26;x>=19;x=x-2) {
|
||||
if ((bitstream2 & 1) == 1) {
|
||||
RawSignal.Pulses[x] = PLUGIN_081_RFLOW/RawSignal.Multiply;
|
||||
RawSignal.Pulses[x-1] = PLUGIN_081_RFHIGH /RawSignal.Multiply;
|
||||
} else {
|
||||
RawSignal.Pulses[x] = PLUGIN_081_RFHIGH /RawSignal.Multiply;
|
||||
RawSignal.Pulses[x-1] = PLUGIN_081_RFLOW/RawSignal.Multiply;
|
||||
}
|
||||
bitstream2 = bitstream2 >> 1;
|
||||
}
|
||||
RawSignal.Pulses[27]=PLUGIN_081_RFSTART/RawSignal.Multiply;
|
||||
RawSignal.Number=27;
|
||||
RawSendRF();
|
||||
success=true;
|
||||
//-----------------------------------------------
|
||||
}
|
||||
return success;
|
||||
}
|
||||
#endif // PLUGIN_081
|
|
@ -0,0 +1,177 @@
|
|||
//#######################################################################################################
|
||||
//## This Plugin is only for use with the RFLink software package ##
|
||||
//## Plugin-082 Mertik Maxitrol ##
|
||||
//#######################################################################################################
|
||||
/*********************************************************************************************\
|
||||
* This Plugin takes care of reception of Mertik Maxitrol / DRU for fireplaces
|
||||
* PCB markings: G6R H4T1.
|
||||
*
|
||||
* Author : StuntTeam
|
||||
* 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!
|
||||
*********************************************************************************************
|
||||
* Changelog: v1.0 initial release
|
||||
*********************************************************************************************
|
||||
* Technical information:
|
||||
*
|
||||
* 0001100101101001011001101
|
||||
* ----------------------- data bits (10=1 01=0)
|
||||
* -- preamble, always 00?
|
||||
* Shortened: (10=1 01=0)
|
||||
* 01100101101001011001101
|
||||
* 0 1 0 0 1 1 0 0 1 0 1 1
|
||||
*
|
||||
* 010011001011
|
||||
* ---- command => 4 bits
|
||||
* -------- address => 8 bits
|
||||
*
|
||||
* command bits:
|
||||
* 0111 7 off
|
||||
* 0011 3 on
|
||||
* 1011 b up
|
||||
* 1101 d down
|
||||
* 1000 8 stop
|
||||
* 1010 a go up
|
||||
* 1100 c go down
|
||||
*
|
||||
* Sample RF packet:
|
||||
* Pulses=26;Pulses(uSec)=475,300,325,700,325,700,325,700,325,700,725,300,725,300,725,300,725,300,725,300,325,700,725,300,725;
|
||||
\*********************************************************************************************/
|
||||
#define MAXITROL_PULSECOUNT 26
|
||||
|
||||
#define PLUGIN_082_RFSTART 100
|
||||
#define PLUGIN_082_RFSPACE 250
|
||||
#define PLUGIN_082_RFLOW 400
|
||||
#define PLUGIN_082_RFHIGH 750
|
||||
|
||||
#ifdef PLUGIN_082
|
||||
boolean Plugin_082(byte function, char *string) {
|
||||
if (RawSignal.Number !=MAXITROL_PULSECOUNT) return false;
|
||||
unsigned int bitstream=0L;
|
||||
byte address=0;
|
||||
byte command=0;
|
||||
byte status=0;
|
||||
//==================================================================================
|
||||
// get bits
|
||||
for(int x=3;x <= MAXITROL_PULSECOUNT-1;x=x+2) {
|
||||
if (RawSignal.Pulses[x]*RAWSIGNAL_SAMPLE_RATE < 550) {
|
||||
if (RawSignal.Pulses[x+1]*RAWSIGNAL_SAMPLE_RATE < 550) return false;
|
||||
bitstream = (bitstream << 1); // 0
|
||||
} else {
|
||||
if (RawSignal.Pulses[x]*RAWSIGNAL_SAMPLE_RATE > 900) return false;
|
||||
if (RawSignal.Pulses[x+1]*RAWSIGNAL_SAMPLE_RATE > 550) return false;
|
||||
bitstream = (bitstream << 1) | 0x1; // 1
|
||||
}
|
||||
}
|
||||
//==================================================================================
|
||||
// all bytes received, make sure packet is valid
|
||||
if (RawSignal.Pulses[1]*RAWSIGNAL_SAMPLE_RATE > 550) return false;
|
||||
if (RawSignal.Pulses[2]*RAWSIGNAL_SAMPLE_RATE > 550) return false;
|
||||
//==================================================================================
|
||||
// Prevent repeating signals from showing up
|
||||
//==================================================================================
|
||||
if( (SignalHash!=SignalHashPrevious) || (RepeatingTimer<millis()) ) {
|
||||
// not seen the RF packet recently
|
||||
if (bitstream == 0) return false; // sanity check
|
||||
} else {
|
||||
// already seen the RF packet recently
|
||||
return true;
|
||||
}
|
||||
//==================================================================================
|
||||
command=(bitstream) & 0x0f; // get address from pulses
|
||||
address=((bitstream)>>4)&0xff;
|
||||
if (command == 0xB) status=1; // up
|
||||
else if (command == 0xD) status=2; // down
|
||||
else if (command == 0x7) status=3; // off
|
||||
else if (command == 0x3) status=4; // on
|
||||
else if (command == 0x8) status=5; // stop
|
||||
else if (command == 0xa) status=6; // go up
|
||||
else if (command == 0xc) status=7; // go down
|
||||
else {
|
||||
return false;
|
||||
}
|
||||
//==================================================================================
|
||||
// Output
|
||||
// ----------------------------------
|
||||
sprintf(pbuffer, "20;%02X;", PKSequenceNumber++); // Node and packet number
|
||||
Serial.print( pbuffer );
|
||||
Serial.print(F("Mertik;")); // Label
|
||||
sprintf(pbuffer, "ID=%02x;", address); // ID
|
||||
Serial.print( pbuffer );
|
||||
sprintf(pbuffer, "SWITCH=%02x;", status);
|
||||
Serial.print( pbuffer );
|
||||
Serial.print(F("CMD="));
|
||||
if (status==1) Serial.print(F("UP;"));
|
||||
if (status==2) Serial.print(F("DOWN;"));
|
||||
if (status==3) Serial.print(F("OFF;"));
|
||||
if (status==4) Serial.print(F("ON;"));
|
||||
if (status==5) Serial.print(F("STOP;"));
|
||||
if (status==6) Serial.print(F("GOUP;"));
|
||||
if (status==7) Serial.print(F("GODOWN;"));
|
||||
Serial.println();
|
||||
//==================================================================================
|
||||
RawSignal.Repeats=true; // suppress repeats of the same RF packet
|
||||
RawSignal.Number=0;
|
||||
return true;
|
||||
}
|
||||
#endif // PLUGIN_082
|
||||
|
||||
#ifdef PLUGIN_TX_082
|
||||
boolean PluginTX_082(byte function, char *string) {
|
||||
boolean success=false;
|
||||
unsigned long bitstream=0L;
|
||||
//10;MERTIK;64;UP;
|
||||
//0123456789012345
|
||||
if (strncasecmp(InputBuffer_Serial+3,"MERTIK;",7) == 0) { // KAKU Command eg.
|
||||
if (InputBuffer_Serial[12] != ';') return false;
|
||||
unsigned int bitstream2=0; // holds last 8 bits
|
||||
|
||||
InputBuffer_Serial[8]=0x30;
|
||||
InputBuffer_Serial[9]=0x78; // Get address from hexadecimal value
|
||||
InputBuffer_Serial[12]=0x00; // Get address from hexadecimal value
|
||||
bitstream=str2int(InputBuffer_Serial+8); // Address (first 16 bits)
|
||||
|
||||
if(strcasecmp(InputBuffer_Serial+13,"stop")==0) bitstream2=0x8;
|
||||
else if(strcasecmp(InputBuffer_Serial+13,"on")==0) bitstream2=0x3;
|
||||
else if(strcasecmp(InputBuffer_Serial+13,"off")==0) bitstream2=0x7;
|
||||
else if(strcasecmp(InputBuffer_Serial+13,"up")==0) bitstream2=0xB;
|
||||
else if(strcasecmp(InputBuffer_Serial+13,"down")==0) bitstream2=0xD;
|
||||
else if(strcasecmp(InputBuffer_Serial+13,"go_up")==0) bitstream2=0xA;
|
||||
else if(strcasecmp(InputBuffer_Serial+13,"go_down")==0) bitstream2=0xC;
|
||||
if (bitstream2==0) return false;
|
||||
//-----------------------------------------------
|
||||
RawSignal.Multiply=50;
|
||||
RawSignal.Repeats=10;
|
||||
RawSignal.Delay=20;
|
||||
RawSignal.Pulses[1]=PLUGIN_082_RFLOW/RawSignal.Multiply;
|
||||
RawSignal.Pulses[2]=PLUGIN_082_RFLOW/RawSignal.Multiply;
|
||||
for(byte x=18;x>=3;x=x-2) {
|
||||
if ((bitstream & 1) == 1) {
|
||||
RawSignal.Pulses[x] = PLUGIN_082_RFLOW/RawSignal.Multiply;
|
||||
RawSignal.Pulses[x-1] = PLUGIN_082_RFHIGH /RawSignal.Multiply;
|
||||
} else {
|
||||
RawSignal.Pulses[x] = PLUGIN_082_RFHIGH /RawSignal.Multiply;
|
||||
RawSignal.Pulses[x-1] = PLUGIN_082_RFLOW/RawSignal.Multiply;
|
||||
}
|
||||
bitstream = bitstream >> 1;
|
||||
}
|
||||
for(byte x=26;x>=19;x=x-2) {
|
||||
if ((bitstream2 & 1) == 1) {
|
||||
RawSignal.Pulses[x] = PLUGIN_082_RFLOW/RawSignal.Multiply;
|
||||
RawSignal.Pulses[x-1] = PLUGIN_082_RFHIGH /RawSignal.Multiply;
|
||||
} else {
|
||||
RawSignal.Pulses[x] = PLUGIN_082_RFHIGH /RawSignal.Multiply;
|
||||
RawSignal.Pulses[x-1] = PLUGIN_082_RFLOW/RawSignal.Multiply;
|
||||
}
|
||||
bitstream2 = bitstream2 >> 1;
|
||||
}
|
||||
RawSignal.Pulses[27]=PLUGIN_082_RFSTART/RawSignal.Multiply;
|
||||
RawSignal.Number=27;
|
||||
RawSendRF();
|
||||
success=true;
|
||||
//-----------------------------------------------
|
||||
}
|
||||
return success;
|
||||
}
|
||||
#endif // PLUGIN_082
|
|
@ -0,0 +1,217 @@
|
|||
//#######################################################################################################
|
||||
//## This Plugin is only for use with Nodo 3.7 Slave Devices (variablesend support) ##
|
||||
//## Plugin-090 Nodo Slave ##
|
||||
//#######################################################################################################
|
||||
// *********************************************************************************************
|
||||
// * This Plugin takes care of reception of Nodo 3.7 Slave Devices
|
||||
// *
|
||||
// * Author : StuntTeam
|
||||
// * 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!
|
||||
// *********************************************************************************************
|
||||
// * Changelog: v1.0 initial release
|
||||
// *********************************************************************************************
|
||||
// ----------------------------------
|
||||
// Nodo Slave Unit 1, 2 and 4 till 9: // Individual sensor data
|
||||
//
|
||||
// Variabele 5 : Temperature
|
||||
// Variabele 6 : Humidity 0 - 100
|
||||
// Variabele 7 : Rain fall
|
||||
// Variabele 8 : Wind speed
|
||||
// Variabele 9 : Wind direction 0 - 15
|
||||
// Variabele 10 : Wind gust
|
||||
// Variabele 11, 12 en 13 : Temperature
|
||||
// Variabele 14 : Humidity 0 - 100
|
||||
// Variabele 15 : UV meter 0 - 1024
|
||||
// Variabele 16 : Barometric pressure
|
||||
//
|
||||
// ----------------------------------
|
||||
// Nodo Slave Unit 10 till 16: // Combined sensor data
|
||||
//
|
||||
// Variabele 5 : Temperature
|
||||
// Variabele 6 : Humidity 0 - 100
|
||||
// Variabele 7 : Rain fall
|
||||
// Variabele 8 : Wind speed
|
||||
// Variabele 9 : Wind direction 0 - 15
|
||||
// Variabele 10 : Wind gust
|
||||
// Variabele 11, 12 en 13 : Temperature
|
||||
// Variabele 14 : Humidity 0 - 100
|
||||
// Variabele 15 : UV meter 0 - 1024
|
||||
// Variabele 16 : Barometric pressure
|
||||
//
|
||||
// ----------------------------------
|
||||
// Nodo Slave Unit 3: // Pulse Meters
|
||||
//
|
||||
// Variabele 1 till 16 : Pulse value 1 till 16
|
||||
//
|
||||
// You can use a Nodo slave device with ID 03 to send variabel numbers 1 til 16
|
||||
// which will be passed to Domoticz as pulse meter values (electricity/water/gas etc.)
|
||||
// ----------------------------------
|
||||
//
|
||||
// * Sample:
|
||||
// * 20;9E;DEBUG;Pulses=194;Pulses(uSec)=3100,900,500,350,1475,375,525,300,1475,375,500,350,450,375,575,250,525,300,1475,375,1450,400,1450,400,425,425,425,425,1425,425,425,425,425,400,425,400,425,400,425,400,425,400,450,400,425,400,450,400,450,400,450,400,425,400,425,425,425,425,425,425,400,425,425,425,400,425,1425,425,400,425,400,425,400,425,400,425,400,425,425,425,400,425,425,425,425,425,1450,425,425,425,425,425,425,425,425,425,400,425,1425,425,1425,425,400,425,400,425,400,425,400,425,400,425,400,425,400,425,425,425,425,425,400,425,400,425,400,425,400,425,400,425,400,425,400,450,400,450,400,450,400,450,400,450,400,450,1400,450,400,450,400,450,400,425,400,450,400,425,1425,425,400,425,1425,425,1425,450,400,450,400,450,375,450,375,450,400,450,1425,450,400,450,1425,425,1425,450,400,450,400,425,400,450,400,450,400,450,400;
|
||||
// * 20;9F;Slave;ID=0307;DEBUG=0014;
|
||||
// * slave nodo 7, var 3 value 14
|
||||
|
||||
// 3100,900,
|
||||
/*( 194-2=192/2 = 96
|
||||
500,350,1475,375,525,300,1475,375,500,350,450,375,575,250,525,300,1475,375,1450,400,1450,400,425,425,425,425,1425,425,425,425,425,400,425,400,425,400,425,400,425,400,450,400,
|
||||
425,400,450,400,450,400,450,400,425,400,425,425,425,425,425,425,400,425,425,425,400,425,1425,425,400,425,400,425,400,425,400,425,400,425,425,425,400,425,425,425,425,425,1450,
|
||||
425,425,425,425,425,425,425,425,425,400,425,1425,425,1425,425,400,425,400,425,400,425,400,425,400,425,400,425,400,425,425,425,425,425,400,425,400,425,400,425,400,425,400,425,
|
||||
400,425,400,450,400,450,400,450,400,450,400,450,400,450,1400,450,400,450,400,450,400,425,400,450,400,425,1425,425,400,425,1425,425,1425,450,400,450,400,450,375,450,375,450,
|
||||
400,450,1425,450,400,450,1425,425,1425,450,400,450,400,425,400,450,400,450,400,450,400;
|
||||
01010000 11100100 00000000 00000000 10000000 00100000 11000000 00000000 00000001 00000101 10000010 11000000
|
||||
00001010 00100111 00000000 00000000 00000001 00000100 00000011 00000000 10000000 10100000 01000001 00000011
|
||||
50E400008020C0010582C0
|
||||
A270000104030080A04103
|
||||
*/
|
||||
// *********************************************************************************************
|
||||
#define NODO_PULSE_MID 1000/RAWSIGNAL_SAMPLE_RATE // PWM: Pulsen langer zijn '1'
|
||||
#define NodoSlave_PULSECOUNT 194
|
||||
|
||||
#ifdef PLUGIN_090
|
||||
|
||||
struct DataBlockStruct { // 16*sizeof(struct DataBlockStruct)+2 = 194 eg. 16*12+2
|
||||
byte Version;
|
||||
byte SourceUnit; // event->SourceUnit=DataBlock.SourceUnit&0x1F; // Maskeer de bits van het Home adres.
|
||||
byte DestinationUnit; // event->DestinationUnit=DataBlock.DestinationUnit; // destination nodo
|
||||
byte Flags;
|
||||
byte Type; // event->Type=DataBlock.Type;
|
||||
byte Command; // event->Command=DataBlock.Command;
|
||||
byte Par1; // event->Par1=DataBlock.Par1;
|
||||
unsigned long Par2; // event->Par2=DataBlock.Par2;
|
||||
byte Checksum;
|
||||
};
|
||||
|
||||
boolean Plugin_090(byte function, char *string) {
|
||||
if (RawSignal.Number!=NodoSlave_PULSECOUNT ) return false; // Per byte twee posities + startbit.
|
||||
byte b,x,y,z;
|
||||
unsigned long varvalue=0L;
|
||||
|
||||
struct DataBlockStruct DataBlock;
|
||||
byte *B=(byte*)&DataBlock; // B wijst naar de eerste byte van de struct
|
||||
z=3; // RawSignal pulse teller: 0=niet gebruiktaantal, 1=startpuls, 2=space na startpuls, 3=1e pulslengte. Dus start loop met drie.
|
||||
|
||||
for(x=0;x<sizeof(struct DataBlockStruct);x++) { // vul alle bytes van de struct
|
||||
b=0;
|
||||
for(y=0;y<=7;y++) { // vul alle bits binnen een byte
|
||||
if((RawSignal.Pulses[z]) > NODO_PULSE_MID)
|
||||
b|=1<<y; // LSB in signaal wordt als eerste verzonden
|
||||
z+=2;
|
||||
}
|
||||
*(B+x)=b;
|
||||
}
|
||||
// xor all bytes to check the checksum value?
|
||||
DataBlock.SourceUnit=DataBlock.SourceUnit &0x1f;
|
||||
//==================================================================================
|
||||
// Er zijn een aantal type Nodo events die op verschillende wijze worden behandeld:
|
||||
//#define NODO_TYPE_EVENT 1
|
||||
//#define NODO_TYPE_PLUGIN_EVENT 4
|
||||
//#define NODO_TYPE_PLUGIN_COMMAND 5
|
||||
if ((DataBlock.Command == 4) && (DataBlock.Type == 1)){ // event->command = DataBlock.Command = 4 = EVENT_VARIABLE
|
||||
// ----------------------------------
|
||||
// Output
|
||||
// ----------------------------------
|
||||
sprintf(pbuffer, "20;%02X;", PKSequenceNumber++); // Node and packet number
|
||||
Serial.print( pbuffer );
|
||||
// ----------------------------------
|
||||
Serial.print(F("Slave;")); // Label
|
||||
//==================================================================================
|
||||
// slave id 03 aka source nodo id 03 => variable 1..6 will be pulse meter data
|
||||
//==================================================================================
|
||||
if (DataBlock.SourceUnit == 3 ) { // Pulse Meter variables
|
||||
sprintf(pbuffer, "ID=%02x%02x%02x;", DataBlock.DestinationUnit, DataBlock.SourceUnit, DataBlock.Par1); // ID
|
||||
Serial.print( pbuffer );
|
||||
varvalue = ul2float(DataBlock.Par2); // convert
|
||||
if ((DataBlock.Par1 < 1) || (DataBlock.Par1 > 16)) { // Unsupported (for now) variable, just show the contents
|
||||
sprintf(pbuffer, "DEBUG=%08lx;", varvalue); // value
|
||||
} else {
|
||||
sprintf(pbuffer, "METER=%08lx;", varvalue); // value
|
||||
}
|
||||
Serial.print( pbuffer );
|
||||
Serial.println();
|
||||
} else
|
||||
//==================================================================================
|
||||
// slave id > 09 aka source nodo id > 09 => Combined variables
|
||||
// slave id < 10 aka source nodo id < 10 => Regular variables
|
||||
//==================================================================================
|
||||
if ((DataBlock.SourceUnit > 0) && (DataBlock.SourceUnit < 17)) {
|
||||
if (DataBlock.SourceUnit > 9 ) {
|
||||
sprintf(pbuffer, "ID=%02x%02x;",DataBlock.SourceUnit , DataBlock.DestinationUnit); // ID
|
||||
} else {
|
||||
sprintf(pbuffer, "ID=%02x%02x%02x;", DataBlock.DestinationUnit, DataBlock.SourceUnit, DataBlock.Par1); // ID
|
||||
}
|
||||
Serial.print( pbuffer );
|
||||
if ((DataBlock.Par1 < 5) || (DataBlock.Par1 > 16)) { // Unsupported (for now) variable, just show the contents
|
||||
int varvalue = ul2float(DataBlock.Par2); // convert
|
||||
sprintf(pbuffer, "DEBUG=%04x;", varvalue); // value
|
||||
} else
|
||||
if (DataBlock.Par1 == 5){ // Variable 5 : temperature
|
||||
int temperature = 10 * ul2float(DataBlock.Par2); // convert
|
||||
if (temperature <= 0) temperature=-temperature | 0x8000; // set high bit for negative temperatures
|
||||
sprintf(pbuffer, "TEMP=%04x;", temperature); // value
|
||||
} else
|
||||
if (DataBlock.Par1 == 6){ // Variable 6 : humidity
|
||||
int humidity = ul2float(DataBlock.Par2) + 0.5; // add 0.5 to make sure it's rounded the way it should and assign as integer to remove decimal value
|
||||
sprintf(pbuffer, "HUM=%02d;", humidity); // value
|
||||
} else
|
||||
if (DataBlock.Par1 == 7){ // Variable 7 : Rain in mm.
|
||||
int rain = ul2float(DataBlock.Par2); // convert
|
||||
sprintf(pbuffer, "RAIN=%04x;", rain); // value
|
||||
} else
|
||||
if (DataBlock.Par1 == 8){ // Variable 8 : Wind speed
|
||||
int winsp = ul2float(DataBlock.Par2); // convert
|
||||
sprintf(pbuffer, "WINSP=%04x;", winsp); // value
|
||||
} else
|
||||
if (DataBlock.Par1 == 9){ // Variable 9 : Wind Direction
|
||||
int windir = ul2float(DataBlock.Par2); // convert
|
||||
sprintf(pbuffer, "WINDIR=%04d;", windir); // value
|
||||
} else
|
||||
if (DataBlock.Par1 == 10){ // Variable 10: Wind Gust
|
||||
int wings = ul2float(DataBlock.Par2); // convert
|
||||
sprintf(pbuffer, "WINGS=%04x;", wings); // value
|
||||
}
|
||||
if ((DataBlock.Par1 > 10) && (DataBlock.Par1 < 14)) { // Variable 11 12 or 13 : emulate temperature sensor
|
||||
int temperature = 10 * ul2float(DataBlock.Par2); // convert
|
||||
if (temperature <= 0) temperature=-temperature | 0x8000; // set high bit for negative temperatures
|
||||
sprintf(pbuffer, "TEMP=%04x;", temperature); // value
|
||||
} else
|
||||
if (DataBlock.Par1 == 14){ // Variable 14 : emulate humidity sensor
|
||||
int humidity = ul2float(DataBlock.Par2) + 0.5; // add 0.5 to make sure it's rounded the way it should and assign as integer to remove decimal value
|
||||
sprintf(pbuffer, "HUM=%02d;", humidity); // value
|
||||
} else
|
||||
if (DataBlock.Par1 == 15){ // Variable 15 : UV sensor
|
||||
int light = ul2float(DataBlock.Par2); // supplied is value between 0 and 1024
|
||||
light = map(light, 0,1024,1,100); // Map value to 1 - 100
|
||||
sprintf(pbuffer, "UV=%04x;", light); // value
|
||||
} else
|
||||
if (DataBlock.Par1 == 16){ // Variable 16 : Barometric pressure sensor
|
||||
int baro = ul2float(DataBlock.Par2); // convert
|
||||
sprintf(pbuffer, "BARO=%04x;", baro); // value
|
||||
}
|
||||
Serial.print( pbuffer );
|
||||
Serial.println();
|
||||
}
|
||||
//==================================================================================
|
||||
} else { // Not a variable event
|
||||
if ((DataBlock.Command == 0) && (DataBlock.Type==0)) return false;
|
||||
// ----------------------------------
|
||||
// Output
|
||||
// ----------------------------------
|
||||
sprintf(pbuffer, "20;%02X;", PKSequenceNumber++); // Node and packet number
|
||||
Serial.print( pbuffer );
|
||||
// ----------------------------------
|
||||
Serial.print(F("Slave;Debug=")); // Label
|
||||
sprintf(pbuffer, "%02x %02x %02x %02x %02x ", DataBlock.DestinationUnit, DataBlock.SourceUnit, DataBlock.Command, DataBlock.Type, DataBlock.Par1);
|
||||
Serial.print( pbuffer );
|
||||
sprintf(pbuffer, "%d;", DataBlock.Par2); // ID
|
||||
Serial.print( pbuffer );
|
||||
Serial.println();
|
||||
}
|
||||
//==================================================================================
|
||||
RawSignal.Repeats=true; // suppress repeats of the same RF packet
|
||||
RawSignal.Number=0;
|
||||
return true;
|
||||
}
|
||||
#endif // PLUGIN_090
|
|
@ -0,0 +1,166 @@
|
|||
//#######################################################################################################
|
||||
//## 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
|
|
@ -0,0 +1,912 @@
|
|||
//#######################################################################################################
|
||||
//## This Plugin is only for use with the RFLink software package ##
|
||||
//## Plugin-48 Oregon V1/2/3 ##
|
||||
//#######################################################################################################
|
||||
/*********************************************************************************************\
|
||||
* This protocol takes care of receiving a few 868 Mhz protocols
|
||||
*
|
||||
* Protocols : Visonic,
|
||||
* ELV EM-Serie: EM-1000S, EM-100-EM, EM-1000-GZ
|
||||
* ELV KS serie: Thermo (AS3), Thermo/Hygro (AS2000, ASH2000, S2000, S2001A, S2001IA, ASH2200, S300IA)
|
||||
* Rain (S2000R), Wind (S2000W), Thermo/Hygro/Baro (S2001I, S2001ID), UV (S2500H)
|
||||
* Pyrano (Strahlungsleistung), Kombi (KS200, KS300)
|
||||
* FS20 FS serie
|
||||
*
|
||||
* Author : StuntTeam
|
||||
* 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!
|
||||
*********************************************************************************************
|
||||
* Changelog: v0.1 beta
|
||||
*********************************************************************************************
|
||||
* Technical information:
|
||||
* Supports Oregon V1, V2 and V3 protocol messages
|
||||
* Core code from https://github.com/Cactusbone/ookDecoder/blob/master/ookDecoder.ino
|
||||
* Copyright (c) 2014 Charly Koza cactusbone@free.fr Copyright (c) 2012 Olivier Lebrun olivier.lebrun@connectingstuff.net
|
||||
* Copyright (c) 2012 Dominique Pierre (zzdomi) Copyright (c) 2010 Jean-Claude Wippler jcw@equi4.com
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation
|
||||
* files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy,
|
||||
* modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software
|
||||
* is furnished to do so, subject to the following conditions:
|
||||
* The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
|
||||
\*********************************************************************************************/
|
||||
#define PLUGIN_ID 101
|
||||
#define PLUGIN_NAME "Few868"
|
||||
|
||||
#define OSV3_PULSECOUNT_MIN 126
|
||||
#define OSV3_PULSECOUNT_MAX 278
|
||||
|
||||
|
||||
// =====================================================================================================
|
||||
class DecodeOOK {
|
||||
protected:
|
||||
byte total_bits, bits, flip, state, pos, data[25];
|
||||
virtual char decode(word width) = 0;
|
||||
public:
|
||||
enum { UNKNOWN, T0, T1, T2, T3, OK, DONE };
|
||||
// -------------------------------------
|
||||
DecodeOOK() { resetDecoder(); }
|
||||
// -------------------------------------
|
||||
bool nextPulse(word width) {
|
||||
if (state != DONE)
|
||||
|
||||
switch (decode(width)) {
|
||||
case -1: resetDecoder(); break;
|
||||
case 1: done(); break;
|
||||
}
|
||||
return isDone();
|
||||
}
|
||||
// -------------------------------------
|
||||
bool isDone() const { return state == DONE; }
|
||||
// -------------------------------------
|
||||
const byte* getData(byte& count) const {
|
||||
count = pos;
|
||||
return data;
|
||||
}
|
||||
// -------------------------------------
|
||||
void resetDecoder() {
|
||||
total_bits = bits = pos = flip = 0;
|
||||
state = UNKNOWN;
|
||||
}
|
||||
// -------------------------------------
|
||||
// add one bit to the packet data pbuffer
|
||||
// -------------------------------------
|
||||
virtual void gotBit(char value) {
|
||||
total_bits++;
|
||||
byte *ptr = data + pos;
|
||||
*ptr = (*ptr >> 1) | (value << 7);
|
||||
|
||||
if (++bits >= 8) {
|
||||
bits = 0;
|
||||
if (++pos >= sizeof data) {
|
||||
resetDecoder();
|
||||
return;
|
||||
}
|
||||
}
|
||||
state = OK;
|
||||
}
|
||||
// -------------------------------------
|
||||
// store a bit using Manchester encoding
|
||||
// -------------------------------------
|
||||
void manchester(char value) {
|
||||
flip ^= value; // manchester code, long pulse flips the bit
|
||||
gotBit(flip);
|
||||
}
|
||||
// -------------------------------------
|
||||
// move bits to the front so that all the bits are aligned to the end
|
||||
// -------------------------------------
|
||||
void alignTail(byte max = 0) {
|
||||
// align bits
|
||||
if (bits != 0) {
|
||||
data[pos] >>= 8 - bits;
|
||||
for (byte i = 0; i < pos; ++i)
|
||||
data[i] = (data[i] >> bits) | (data[i + 1] << (8 - bits));
|
||||
bits = 0;
|
||||
}
|
||||
// optionally shift bytes down if there are too many of 'em
|
||||
if (max > 0 && pos > max) {
|
||||
byte n = pos - max;
|
||||
pos = max;
|
||||
for (byte i = 0; i < pos; ++i)
|
||||
data[i] = data[i + n];
|
||||
}
|
||||
}
|
||||
// -------------------------------------
|
||||
void reverseBits() {
|
||||
for (byte i = 0; i < pos; ++i) {
|
||||
byte b = data[i];
|
||||
for (byte j = 0; j < 8; ++j) {
|
||||
data[i] = (data[i] << 1) | (b & 1);
|
||||
b >>= 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
// -------------------------------------
|
||||
void reverseNibbles() {
|
||||
for (byte i = 0; i < pos; ++i)
|
||||
data[i] = (data[i] << 4) | (data[i] >> 4);
|
||||
}
|
||||
// -------------------------------------
|
||||
void done() {
|
||||
while (bits)
|
||||
gotBit(0); // padding
|
||||
state = DONE;
|
||||
}
|
||||
};
|
||||
|
||||
// 868 MHz decoders
|
||||
|
||||
/// OOK decoder for Visonic devices.
|
||||
class VisonicDecoder : public DecodeOOK {
|
||||
public:
|
||||
VisonicDecoder () {}
|
||||
|
||||
virtual char decode (word width) {
|
||||
if (200 <= width && width < 1000) {
|
||||
byte w = width >= 600;
|
||||
switch (state) {
|
||||
case UNKNOWN:
|
||||
case OK:
|
||||
state = w == 0 ? T0 : T1;
|
||||
break;
|
||||
case T0:
|
||||
gotBit(!w);
|
||||
if (w)
|
||||
return 0;
|
||||
break;
|
||||
case T1:
|
||||
gotBit(!w);
|
||||
if (!w)
|
||||
return 0;
|
||||
break;
|
||||
}
|
||||
// sync error, flip all the preceding bits to resync
|
||||
for (byte i = 0; i <= pos; ++i)
|
||||
data[i] ^= 0xFF;
|
||||
} else if (width >= 2500 && 8 * pos + bits >= 36 && state == OK) {
|
||||
for (byte i = 0; i < 4; ++i)
|
||||
gotBit(0);
|
||||
alignTail(5); // keep last 40 bits
|
||||
// only report valid packets
|
||||
byte b = data[0] ^ data[1] ^ data[2] ^ data[3] ^ data[4];
|
||||
if ((b & 0xF) == (b >> 4))
|
||||
return 1;
|
||||
} else
|
||||
return -1;
|
||||
return 0;
|
||||
}
|
||||
};
|
||||
|
||||
/// OOK decoder for FS20 type EM devices.
|
||||
class EMxDecoder : public DecodeOOK {
|
||||
public:
|
||||
EMxDecoder () : DecodeOOK (30) {} // ignore packets repeated within 3 sec
|
||||
|
||||
// see also http://fhz4linux.info/tiki-index.php?page=EM+Protocol
|
||||
virtual char decode (word width) {
|
||||
if (200 <= width && width < 1000) {
|
||||
byte w = width >= 600;
|
||||
switch (state) {
|
||||
case UNKNOWN:
|
||||
if (w == 0)
|
||||
++flip;
|
||||
else if (flip > 20)
|
||||
state = OK;
|
||||
else
|
||||
return -1;
|
||||
break;
|
||||
case OK:
|
||||
if (w == 0)
|
||||
state = T0;
|
||||
else
|
||||
return -1;
|
||||
break;
|
||||
case T0:
|
||||
gotBit(w);
|
||||
break;
|
||||
}
|
||||
} else if (width >= 1500 && pos >= 9)
|
||||
return 1;
|
||||
else
|
||||
return -1;
|
||||
return 0;
|
||||
}
|
||||
};
|
||||
|
||||
/// OOK decoder for FS20 type KS devices.
|
||||
class KSxDecoder : public DecodeOOK {
|
||||
public:
|
||||
KSxDecoder () {}
|
||||
|
||||
// see also http://www.dc3yc.homepage.t-online.de/protocol.htm
|
||||
virtual char decode (word width) {
|
||||
if (200 <= width && width < 1000) {
|
||||
byte w = width >= 600;
|
||||
switch (state) {
|
||||
case UNKNOWN:
|
||||
gotBit(w);
|
||||
bits = pos = 0;
|
||||
if (data[0] != 0x95)
|
||||
state = UNKNOWN;
|
||||
break;
|
||||
case OK:
|
||||
state = w == 0 ? T0 : T1;
|
||||
break;
|
||||
case T0:
|
||||
gotBit(1);
|
||||
if (!w)
|
||||
return -1;
|
||||
break;
|
||||
case T1:
|
||||
gotBit(0);
|
||||
if (w)
|
||||
return -1;
|
||||
break;
|
||||
}
|
||||
} else if (width >= 1500 && pos >= 6)
|
||||
return 1;
|
||||
else
|
||||
return -1;
|
||||
return 0;
|
||||
}
|
||||
};
|
||||
|
||||
/// OOK decoder for FS20 type FS devices.
|
||||
class FSxDecoder : public DecodeOOK {
|
||||
public:
|
||||
FSxDecoder () {}
|
||||
|
||||
// see also http://fhz4linux.info/tiki-index.php?page=FS20%20Protocol
|
||||
virtual char decode (word width) {
|
||||
if (300 <= width && width < 775) {
|
||||
byte w = width >= 500;
|
||||
switch (state) {
|
||||
case UNKNOWN:
|
||||
if (w == 0)
|
||||
++flip;
|
||||
else if (flip > 20)
|
||||
state = T1;
|
||||
else
|
||||
return -1;
|
||||
break;
|
||||
case OK:
|
||||
state = w == 0 ? T0 : T1;
|
||||
break;
|
||||
case T0:
|
||||
gotBit(0);
|
||||
if (w)
|
||||
return -1;
|
||||
break;
|
||||
case T1:
|
||||
gotBit(1);
|
||||
if (!w)
|
||||
return -1;
|
||||
break;
|
||||
}
|
||||
} else if (width >= 1500 && pos >= 5)
|
||||
return 1;
|
||||
else
|
||||
return -1;
|
||||
return 0;
|
||||
}
|
||||
};
|
||||
|
||||
// =====================================================================================================
|
||||
// =====================================================================================================
|
||||
|
||||
|
||||
OregonDecoderV1 orscV1;
|
||||
OregonDecoderV2 orscV2;
|
||||
OregonDecoderV3 orscV3;
|
||||
|
||||
volatile word pulse;
|
||||
// =====================================================================================================
|
||||
// =====================================================================================================
|
||||
byte osdata[13];
|
||||
|
||||
void reportSerial(class DecodeOOK& decoder) {
|
||||
byte pos;
|
||||
const byte* data = decoder.getData(pos);
|
||||
for (byte i = 0; i < pos; ++i) {
|
||||
if (i < 13) osdata[i]=data[i];
|
||||
}
|
||||
decoder.resetDecoder();
|
||||
}
|
||||
// =====================================================================================================
|
||||
// calculate a packet checksum by performing a
|
||||
byte checksum(byte type, int count, byte check) {
|
||||
byte calc=0;
|
||||
// type 1, add all nibbles, deduct 10
|
||||
if (type == 1) {
|
||||
for(byte i = 0; i<count;i++) {
|
||||
calc += (osdata[i]&0xF0) >> 4;
|
||||
calc += (osdata[i]&0xF);
|
||||
}
|
||||
calc=calc-10;
|
||||
} else
|
||||
// type 2, add all nibbles up to count, add the 13th nibble , deduct 10
|
||||
if (type == 2) {
|
||||
for(byte i = 0; i<count;i++) {
|
||||
calc += (osdata[i]&0xF0) >> 4;
|
||||
calc += (osdata[i]&0xF);
|
||||
}
|
||||
calc += (osdata[6]&0xF);
|
||||
calc=calc-10;
|
||||
} else
|
||||
// type 3, add all nibbles up to count, subtract 10 only use the low 4 bits for the compare
|
||||
if (type == 3) {
|
||||
for(byte i = 0; i<count;i++) {
|
||||
calc += (osdata[i]&0xF0) >> 4;
|
||||
calc += (osdata[i]&0xF);
|
||||
}
|
||||
calc=calc-10;
|
||||
calc=(calc&0x0f);
|
||||
} else
|
||||
if (type == 4) {
|
||||
for(byte i = 0; i<count;i++) {
|
||||
calc += (osdata[i]&0xF0) >> 4;
|
||||
calc += (osdata[i]&0xF);
|
||||
}
|
||||
calc=calc-10;
|
||||
|
||||
}
|
||||
if (check == calc ) return 0;
|
||||
return 1;
|
||||
}
|
||||
// =====================================================================================================
|
||||
boolean Plugin_048(byte function, char *string) {
|
||||
boolean success=false;
|
||||
|
||||
#ifdef PLUGIN_048_CORE
|
||||
if ((RawSignal.Number < OSV3_PULSECOUNT_MIN) || (RawSignal.Number > OSV3_PULSECOUNT_MAX) ) return false;
|
||||
|
||||
byte basevar=0;
|
||||
byte rc=0;
|
||||
byte found = 0;
|
||||
byte channel = 0;
|
||||
|
||||
int temp = 0;
|
||||
byte hum = 0;
|
||||
int comfort = 0;
|
||||
int baro = 0;
|
||||
int forecast = 0;
|
||||
int uv = 0;
|
||||
int wdir = 0;
|
||||
int wspeed = 0;
|
||||
int awspeed = 0;
|
||||
int rain = 0;
|
||||
int raintot = 0;
|
||||
|
||||
word p = pulse;
|
||||
// ==================================================================================
|
||||
for (int x = 0; x < RawSignal.Number; x++) {
|
||||
p = RawSignal.Pulses[x]*RAWSIGNAL_SAMPLE_RATE;
|
||||
if (p != 0) {
|
||||
if (orscV1.nextPulse(p)) {
|
||||
reportSerial(orscV1);
|
||||
found=1;
|
||||
}
|
||||
if (orscV2.nextPulse(p)) {
|
||||
reportSerial(orscV2);
|
||||
found=2;
|
||||
}
|
||||
if (orscV3.nextPulse(p)) {
|
||||
reportSerial(orscV3);
|
||||
found=3;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (found == 0) break;
|
||||
|
||||
// ==================================================================================
|
||||
// Protocol and device info:
|
||||
// ==================================================================================
|
||||
//Serial.print("Oregon V");
|
||||
//Serial.print(found);
|
||||
//Serial.print(": ");
|
||||
//for(byte x=0; x<13;x++) {
|
||||
// Serial.print( osdata[x],HEX );
|
||||
// Serial.print((" "));
|
||||
//}
|
||||
//Serial.println();
|
||||
//Serial.print("Oregon ID=");
|
||||
unsigned int id=(osdata[0]<<8)+ (osdata[1]);
|
||||
rc=osdata[0];
|
||||
//Serial.println(id,HEX);
|
||||
// ==================================================================================
|
||||
// Process the various device types:
|
||||
// ==================================================================================
|
||||
// Oregon V1 packet structure
|
||||
// SL-109H, AcuRite 09955
|
||||
// TEMP + CRC
|
||||
// ==================================================================================
|
||||
// 8487101C
|
||||
// 84+87+10=11B > 1B+1 = 1C
|
||||
if (found==1) { // OSV1
|
||||
int sum = osdata[0]+osdata[1]+osdata[2]; // max. value is 0x2FD
|
||||
sum= (sum &0xff) + (sum>>8); // add overflow to low byte
|
||||
if (osdata[3] != (sum & 0xff) ) {
|
||||
//Serial.println("CRC Error");
|
||||
break;
|
||||
}
|
||||
// -------------
|
||||
temp = ((osdata[2]>>4) * 100) + ((osdata[1] & 0x0F) * 10) + ((osdata[1] >> 4));
|
||||
if ((osdata[2] & 0x02) == 2) temp=temp | 0x8000; // bit 1 set when temp is negative, set highest bit on temp valua
|
||||
// ----------------------------------
|
||||
// Output
|
||||
// ----------------------------------
|
||||
sprintf(pbuffer, "20;%02X;", PKSequenceNumber++); // Node and packet number
|
||||
Serial.print( pbuffer );
|
||||
// ----------------------------------
|
||||
Serial.print("OregonV1;"); // Label
|
||||
sprintf(pbuffer, "ID=00%02x;", rc); // ID
|
||||
Serial.print( pbuffer );
|
||||
sprintf(pbuffer, "TEMP=%04x;", temp);
|
||||
Serial.print( pbuffer );
|
||||
Serial.println();
|
||||
}
|
||||
// ==================================================================================
|
||||
// ea4c Outside (Water) Temperature: THC238, THC268, THN132N, THWR288A, THRN122N, THN122N, AW129, AW131
|
||||
// TEMP + BAT + CRC
|
||||
// ca48 Pool (Water) Temperature: THWR800
|
||||
// 0a4d Indoor Temperature: THR128, THR138, THC138
|
||||
// ==================================================================================
|
||||
// OSV2 EA4C20725C21D083 // THN132N
|
||||
// OSV2 EA4C101360193023 // THN132N
|
||||
// OSV2 EA4C40F85C21D0D4 // THN132N
|
||||
// OSV2 EA4C20809822D013
|
||||
// 0123456789012345
|
||||
// 0 1 2 3 4 5 6 7
|
||||
if(id == 0xea4c || id == 0xca48 || id == 0x0a4d) {
|
||||
byte sum=(osdata[7]&0x0f) <<4;
|
||||
sum=sum+(osdata[6]>>4);
|
||||
if ( checksum(2,6, sum) !=0) { // checksum = all nibbles 0-11+13 results is nibbles 15 <<4 + 12
|
||||
//Serial.println("CRC Error");
|
||||
break;
|
||||
}
|
||||
// -------------
|
||||
temp = ((osdata[5]>>4) * 100) + ((osdata[5] & 0x0F) * 10) + ((osdata[4] >> 4));
|
||||
if ((osdata[6] & 0x0F) >= 8) temp=temp | 0x8000;
|
||||
// ----------------------------------
|
||||
// Output
|
||||
// ----------------------------------
|
||||
sprintf(pbuffer, "20;%02X;", PKSequenceNumber++); // Node and packet number
|
||||
Serial.print( pbuffer );
|
||||
// ----------------------------------
|
||||
Serial.print("Oregon Temp;"); // Label
|
||||
sprintf(pbuffer, "ID=%02x%02x;", rc,osdata[2]); // ID
|
||||
Serial.print( pbuffer );
|
||||
sprintf(pbuffer, "TEMP=%04x;", temp);
|
||||
Serial.print( pbuffer );
|
||||
if ((osdata[3] & 0x0F) >= 4) {
|
||||
Serial.print("BAT=LOW;");
|
||||
} else {
|
||||
Serial.print("BAT=OK;");
|
||||
}
|
||||
Serial.println();
|
||||
} else
|
||||
// ==================================================================================
|
||||
// 1a2d Indoor Temp/Hygro: THGN122N, THGN123N, THGR122NX, THGR228N, THGR238, THGR268, THGR122X
|
||||
// 1a3d Outside Temp/Hygro: THGR918, THGRN228NX, THGN500
|
||||
// fa28 Indoor Temp/Hygro: THGR810
|
||||
// *aac Outside Temp/Hygro: RTGR328N
|
||||
// ca2c Outside Temp/Hygro: THGR328N
|
||||
// fab8 Outside Temp/Hygro: WTGR800
|
||||
// TEMP + HUM sensor + BAT + CRC
|
||||
// ==================================================================================
|
||||
// OSV2 AACC13783419008250AD[RTGR328N,...] Id:78 ,Channel:0 ,temp:19.30 ,hum:20 ,bat:10
|
||||
// OSV2 1A2D40C4512170463EE6[THGR228N,...] Id:C4 ,Channel:3 ,temp:21.50 ,hum:67 ,bat:90
|
||||
// OSV2 1A2D1072512080E73F2C[THGR228N,...] Id:72 ,Channel:1 ,temp:20.50 ,hum:78 ,bat:90
|
||||
// OSV2 1A2D103742197005378E // THGR228N
|
||||
// OSV3 FA28A428202290834B46 //
|
||||
// OSV2 1A2D1002 02060552A4C
|
||||
// 1A3D10D91C273083..
|
||||
// 1A3D10D90C284083..
|
||||
// OSV3 FA2814A93022304443BE // THGR810
|
||||
// 01234567890123456789
|
||||
// 0 1 2 3 4 5
|
||||
// F+A+2+8+1+4+A+9+3+0+2+2+3+0+4+4=4d-a=43
|
||||
if(id == 0xfa28 || id == 0x1a2d || id == 0x1a3d || (id&0xfff)==0xACC || id == 0xca2c || id == 0xfab8 ) {
|
||||
if ( checksum(1,8,osdata[8]) !=0) break; // checksum = all nibbles 0-15 results is nibbles 16.17
|
||||
// -------------
|
||||
temp = ((osdata[5]>>4) * 100) + ((osdata[5] & 0x0F) * 10) + ((osdata[4] >> 4));
|
||||
if ((osdata[6] & 0x0F) >= 8) temp=temp | 0x8000;
|
||||
// -------------
|
||||
hum = ((osdata[7] & 0x0F)*10)+ (osdata[6] >> 4);
|
||||
// ----------------------------------
|
||||
// Output
|
||||
// ----------------------------------
|
||||
sprintf(pbuffer, "20;%02X;", PKSequenceNumber++); // Node and packet number
|
||||
Serial.print( pbuffer );
|
||||
// ----------------------------------
|
||||
Serial.print("Oregon TempHygro;"); // Label
|
||||
sprintf(pbuffer, "ID=%02x%02x;", rc,osdata[2]); // ID
|
||||
Serial.print( pbuffer );
|
||||
sprintf(pbuffer, "TEMP=%04x;", temp);
|
||||
Serial.print( pbuffer );
|
||||
sprintf(pbuffer, "HUM=%02x;", hum);
|
||||
Serial.print( pbuffer );
|
||||
if ((osdata[3] & 0x0F) >= 4) {
|
||||
Serial.print("BAT=LOW;");
|
||||
} else {
|
||||
Serial.print("BAT=OK;");
|
||||
}
|
||||
Serial.println();
|
||||
} else
|
||||
// ==================================================================================
|
||||
// 5a5d Indoor Temp/Hygro/Baro: Huger - BTHR918
|
||||
// 5a6d Indoor Temp/Hygro/Baro: BTHR918N, BTHR968. BTHG968
|
||||
// TEMP + HUM + BARO + FORECAST + BAT
|
||||
// NO CRC YET
|
||||
// ==================================================================================
|
||||
// 5A 6D 00 7A 10 23 30 83 86 31
|
||||
// 5+a+6+d+7+a+1+2+3+3+8+3=47 -a=3d +8=4f +8+6=55
|
||||
// 5+a+6+d+7+a+1+2+3+3=3c-a=32
|
||||
// 0 1 2 3 4 5 6 7 8 9
|
||||
if(id == 0x5a6d || id == 0x5a5d || id == 0x5d60) {
|
||||
// -------------
|
||||
temp = ((osdata[5]>>4) * 100) + ((osdata[5] & 0x0F) * 10) + ((osdata[4] >> 4));
|
||||
if ((osdata[6] & 0x0F) >= 8) temp=temp | 0x8000;
|
||||
// -------------
|
||||
hum = ((osdata[7] & 0x0F)*10)+ (osdata[6] >> 4);
|
||||
|
||||
//0: normal, 4: comfortable, 8: dry, C: wet
|
||||
int tmp_comfort = osdata[7] >> 4;
|
||||
if (tmp_comfort == 0x00)
|
||||
comfort=0;
|
||||
else if (tmp_comfort == 0x04)
|
||||
comfort=1;
|
||||
else if (tmp_comfort == 0x08)
|
||||
comfort=2;
|
||||
else if (tmp_comfort == 0x0C)
|
||||
comfort=3;
|
||||
|
||||
// -------------
|
||||
baro = (osdata[8] + 856); // max value = 1111 / 0x457
|
||||
|
||||
//2: cloudy, 3: rainy, 6: partly cloudy, C: sunny
|
||||
int tmp_forecast = osdata[9]>>4;
|
||||
if (tmp_forecast == 0x02)
|
||||
forecast = 3;
|
||||
else if (tmp_forecast == 0x03)
|
||||
forecast = 4;
|
||||
else if (tmp_forecast == 0x06)
|
||||
forecast = 2;
|
||||
else if (tmp_forecast == 0x0C)
|
||||
forecast = 1;
|
||||
|
||||
// ----------------------------------
|
||||
// Output
|
||||
// ----------------------------------
|
||||
sprintf(pbuffer, "20;%02X;", PKSequenceNumber++); // Node and packet number
|
||||
Serial.print( pbuffer );
|
||||
// ----------------------------------
|
||||
Serial.print("Oregon BTHR;"); // Label
|
||||
sprintf(pbuffer, "ID=%02x%02x;", rc,osdata[2]); // ID
|
||||
Serial.print( pbuffer );
|
||||
sprintf(pbuffer, "TEMP=%04x;", temp);
|
||||
Serial.print( pbuffer );
|
||||
sprintf(pbuffer, "HUM=%02x;", hum);
|
||||
Serial.print( pbuffer );
|
||||
sprintf(pbuffer, "HSTATUS=%d;", comfort);
|
||||
Serial.print( pbuffer );
|
||||
sprintf(pbuffer, "BARO=%04x;", baro);
|
||||
Serial.print( pbuffer );
|
||||
sprintf(pbuffer, "BFORECAST=%d;", forecast);
|
||||
Serial.print( pbuffer );
|
||||
|
||||
//below is not correct, and for now discarded
|
||||
//if (((osdata[3] & 0x0F) & 0x04) != 0) {
|
||||
// Serial.print("BAT=LOW;");
|
||||
//} else {
|
||||
// Serial.print("BAT=OK;");
|
||||
//}
|
||||
Serial.println();
|
||||
} else
|
||||
// ==================================================================================
|
||||
// 2914 Rain Gauge:
|
||||
// 2d10 Rain Gauge:
|
||||
// 2a1d Rain Gauge: RGR126, RGR682, RGR918, PCR122
|
||||
// 2A1D0065502735102063
|
||||
// 2+A+1+D+0+0+6+5+5+0+2+7+3+5+1+0+2+0=3e-a=34 != 63
|
||||
// ==================================================================================
|
||||
if(id == 0x2a1d || id == 0x2d10 || id == 0x2914) { // Rain sensor
|
||||
//Checksum - add all nibbles from 0 to 8, subtract 9 and compare
|
||||
/*
|
||||
int cs = 0;
|
||||
for (byte i = 0; i < pos-2; ++i) { //all but last byte
|
||||
cs += data[i] >> 4;
|
||||
cs += data[i] & 0x0F;
|
||||
}
|
||||
int csc = (data[8] >> 4) + ((data[9] & 0x0F)*16);
|
||||
cs -= 9; //my version as A fails?
|
||||
Serial.print(csc);
|
||||
Serial.print(" vs ");
|
||||
Serial.println(cs);
|
||||
*/
|
||||
rain = ((osdata[5]>>4) * 100) + ((osdata[5] & 0x0F) * 10) + (osdata[4] >> 4);
|
||||
raintot = ((osdata[7] >> 4) * 10) + (osdata[6]>>4);
|
||||
// ----------------------------------
|
||||
// Output
|
||||
// ----------------------------------
|
||||
sprintf(pbuffer, "20;%02X;", PKSequenceNumber++); // Node and packet number
|
||||
Serial.print( pbuffer );
|
||||
// ----------------------------------
|
||||
Serial.print("Oregon Rain;"); // Label
|
||||
sprintf(pbuffer, "ID=%02x%02x;", rc,osdata[3]); // ID
|
||||
Serial.print( pbuffer );
|
||||
sprintf(pbuffer, "RAIN=%04x;", rain);
|
||||
Serial.print( pbuffer );
|
||||
sprintf(pbuffer, "RAINTOT=%04x;", raintot);
|
||||
Serial.print( pbuffer );
|
||||
if ((osdata[3] & 0x0F) >= 4) {
|
||||
Serial.print("BAT=LOW;");
|
||||
} else {
|
||||
Serial.print("BAT=OK;");
|
||||
}
|
||||
Serial.println();
|
||||
} else
|
||||
// ==================================================================================
|
||||
// 2a19 Rain Gauge: PCR800
|
||||
// RAIN + BAT + CRC
|
||||
// ==================================================================================
|
||||
// OSV3 2A19048E399393250010
|
||||
// 01234567890123456789
|
||||
// 0 1 2 3 4 5 6 7 8 9
|
||||
// 2+A+1+9+0+4+8+E+3+9+9+3+9+3+2+5=5b-A=51 => 10
|
||||
if(id == 0x2a19) { // Rain sensor
|
||||
int sum = (osdata[9] >> 4);
|
||||
if ( checksum(3,9,sum) !=0) { // checksum = all nibbles 0-17 result is nibble 18
|
||||
//Serial.print("CRC Error, ");
|
||||
break;
|
||||
}
|
||||
rain = ((osdata[5]>>4) * 100) + ((osdata[5] & 0x0F) * 10) + (osdata[4] >> 4);
|
||||
//Serial.print(" RainTotal=");
|
||||
//raintot = ((osdata[7] >> 4) * 10) + (osdata[6]>>4);
|
||||
//Serial.print(raintot);
|
||||
// ----------------------------------
|
||||
// Output
|
||||
// ----------------------------------
|
||||
sprintf(pbuffer, "20;%02X;", PKSequenceNumber++); // Node and packet number
|
||||
Serial.print( pbuffer );
|
||||
// ----------------------------------
|
||||
Serial.print("Oregon Rain2;"); // Label
|
||||
sprintf(pbuffer, "ID=%02x%02x;", rc,osdata[4]); // ID
|
||||
Serial.print( pbuffer );
|
||||
sprintf(pbuffer, "RAIN=%04x;", rain);
|
||||
Serial.print( pbuffer );
|
||||
//sprintf(pbuffer, "RAINTOT=%04x;", raintot);
|
||||
//Serial.print( pbuffer );
|
||||
if ((osdata[3] & 0x0F) >= 4) {
|
||||
Serial.print("BAT=LOW;");
|
||||
} else {
|
||||
Serial.print("BAT=OK;");
|
||||
}
|
||||
Serial.println();
|
||||
} else
|
||||
// ==================================================================================
|
||||
// 1a89 Anemometer: WGR800
|
||||
// WIND DIR + SPEED + AV SPEED + CRC
|
||||
// ==================================================================================
|
||||
// OSV3 1A89048800C026400543
|
||||
// OSV3 1A89048800C00431103B
|
||||
// OSV3 1a89048848c00000003e W
|
||||
// OSV3 1a890488c0c00000003e E
|
||||
// 1A89042CB0C047000147
|
||||
// 0 1 2 3 4 5 6 7 8 9
|
||||
// 1+A+8+9+0+4+8+8+0+0+C+0+0+4+3+1+1+0=45-a=3b
|
||||
if(id == 0x1a89) { // Wind sensor
|
||||
if ( checksum(1,9,osdata[9]) !=0) break;
|
||||
Serial.print(" WINDIR=");
|
||||
wdir=(osdata[4] >> 4);
|
||||
wdir=wdir*225;
|
||||
wdir=wdir/10;
|
||||
Serial.print(wdir);
|
||||
// -------------
|
||||
wspeed = (osdata[6] >> 4) * 10;
|
||||
wspeed = wspeed + (osdata[6] &0x0f) * 100;
|
||||
wspeed = wspeed + (osdata[5] &0x0f);
|
||||
// -------------
|
||||
awspeed = (osdata[8] >> 4) * 100;
|
||||
awspeed = awspeed + (osdata[7] &0x0f) * 10;
|
||||
awspeed = awspeed + (osdata[7] >> 4);
|
||||
// ----------------------------------
|
||||
// Output
|
||||
// ----------------------------------
|
||||
sprintf(pbuffer, "20;%02X;", PKSequenceNumber++); // Node and packet number
|
||||
Serial.print( pbuffer );
|
||||
// ----------------------------------
|
||||
Serial.print("Oregon Wind;"); // Label
|
||||
sprintf(pbuffer, "ID=%02x%02x;", rc,osdata[2]); // ID
|
||||
Serial.print( pbuffer );
|
||||
sprintf(pbuffer, "WINDIR=%04x;", wdir);
|
||||
Serial.print( pbuffer );
|
||||
sprintf(pbuffer, "WINSP=%04x;", wspeed);
|
||||
Serial.print( pbuffer );
|
||||
sprintf(pbuffer, "AWINSP=%04x;", awspeed);
|
||||
Serial.print( pbuffer );
|
||||
if ((osdata[3] & 0x0F) >= 4) {
|
||||
Serial.print("BAT=LOW;");
|
||||
} else {
|
||||
Serial.print("BAT=OK;");
|
||||
}
|
||||
Serial.println();
|
||||
} else
|
||||
// ==================================================================================
|
||||
// 3a0d Anemometer: Huger-STR918, WGR918
|
||||
// 1984 Anemometer:
|
||||
// 1994 Anemometer:
|
||||
// WIND DIR + SPEED + AV SPEED + BAT + CRC
|
||||
// 3A0D006F400800000031
|
||||
// ==================================================================================
|
||||
if(id == 0x3A0D || id == 0x1984 || id == 0x1994 ) {
|
||||
if ( checksum(1,9,osdata[9]) !=0) {
|
||||
Serial.print("CRC Error, ");
|
||||
//break;
|
||||
}
|
||||
wdir = ((osdata[5]>>4) * 100) + ((osdata[5] & 0x0F * 10) ) + (osdata[4] >> 4);
|
||||
wspeed = ((osdata[7] & 0x0F) * 100) + ((osdata[6]>>4) * 10) + ((osdata[6] & 0x0F)) ;
|
||||
awspeed = ((osdata[8]>>4) * 100) + ((osdata[8] & 0x0F) * 10)+((osdata[7] >>4)) ;
|
||||
// ----------------------------------
|
||||
// Output
|
||||
// ----------------------------------
|
||||
sprintf(pbuffer, "20;%02X;", PKSequenceNumber++); // Node and packet number
|
||||
Serial.print( pbuffer );
|
||||
// ----------------------------------
|
||||
Serial.print("Oregon Wind2;"); // Label
|
||||
sprintf(pbuffer, "ID=%02x%02x;", rc,osdata[2]); // ID
|
||||
Serial.print( pbuffer );
|
||||
sprintf(pbuffer, "WINDIR=%04x;", wdir);
|
||||
Serial.print( pbuffer );
|
||||
sprintf(pbuffer, "WINSP=%04x;", wspeed);
|
||||
Serial.print( pbuffer );
|
||||
sprintf(pbuffer, "AWINSP=%04x;", awspeed);
|
||||
Serial.print( pbuffer );
|
||||
if ((osdata[3] & 0x0F) >= 4) {
|
||||
Serial.print("BAT=LOW;");
|
||||
} else {
|
||||
Serial.print("BAT=OK;");
|
||||
}
|
||||
Serial.println();
|
||||
} else
|
||||
// ==================================================================================
|
||||
// ea7c UV Sensor: UVN128, UV138
|
||||
// UV + BAT
|
||||
// NO CRC YET
|
||||
// ==================================================================================
|
||||
if(id == 0xea7c) {
|
||||
uv=((osdata[5] & 0x0F) * 10) + (osdata[4] >> 4);
|
||||
Serial.print(uv);
|
||||
// ----------------------------------
|
||||
// Output
|
||||
// ----------------------------------
|
||||
sprintf(pbuffer, "20;%02X;", PKSequenceNumber++); // Node and packet number
|
||||
Serial.print( pbuffer );
|
||||
// ----------------------------------
|
||||
Serial.print("Oregon UVN128/138;"); // Label
|
||||
sprintf(pbuffer, "ID=%02x%02x;", rc,osdata[2]); // ID
|
||||
Serial.print( pbuffer );
|
||||
sprintf(pbuffer, "UV=%04x;", uv);
|
||||
Serial.print( pbuffer );
|
||||
if ((osdata[3] & 0x0F) >= 4) {
|
||||
Serial.print("BAT=LOW;");
|
||||
} else {
|
||||
Serial.print("BAT=OK;");
|
||||
}
|
||||
Serial.println();
|
||||
} else
|
||||
// ==================================================================================
|
||||
// da78 UV Sensor: UVN800
|
||||
// UV
|
||||
// NO CRC YET
|
||||
// ==================================================================================
|
||||
if( id == 0xda78) {
|
||||
uv=(osdata[6] & 0xf0) + (osdata[5] &0x0f) ;
|
||||
// ----------------------------------
|
||||
// Output
|
||||
// ----------------------------------
|
||||
sprintf(pbuffer, "20;%02X;", PKSequenceNumber++); // Node and packet number
|
||||
Serial.print( pbuffer );
|
||||
// ----------------------------------
|
||||
Serial.print("Oregon UVN800;"); // Label
|
||||
sprintf(pbuffer, "ID=%02x%02x;", rc,osdata[2]); // ID
|
||||
Serial.print( pbuffer );
|
||||
sprintf(pbuffer, "UV=%04x;", uv);
|
||||
Serial.print( pbuffer );
|
||||
if ((osdata[3] & 0x0F) >= 4) {
|
||||
Serial.print("BAT=LOW;");
|
||||
} else {
|
||||
Serial.print("BAT=OK;");
|
||||
}
|
||||
Serial.println();
|
||||
} else
|
||||
// ==================================================================================
|
||||
// *aec Date&Time: RTGR328N
|
||||
// NO CRC YET
|
||||
// ==================================================================================
|
||||
// 8AEA1378077214924242C16CBD 21:49 29/04/2014
|
||||
// 0 1 2 3 4 5 6 7 8 9 0 1 2
|
||||
// 8+A+E+A+1+3+7+8+0+7+7+2+1+4+9+2+4+2+4+2+C+1+6+C=88 != BD
|
||||
// Date & Time
|
||||
//if( (id &0xfff) == 0xaea) {
|
||||
// Serial.print("RTGR328N RC: ");
|
||||
// Serial.print(osdata[3], HEX);
|
||||
// Serial.print(" Date: ");
|
||||
// Serial.print( (osdata[9] >> 4) + 10 * (osdata[10] & 0xf) );
|
||||
// Serial.print(" - ");
|
||||
// Serial.print( osdata[8] >> 4 );
|
||||
// Serial.print(" - ");
|
||||
// Serial.print( (osdata[7] >> 4) + 10 * (osdata[8] & 0xf) );
|
||||
// Serial.print(" Time: ");
|
||||
// Serial.print( (osdata[6] >> 4) + 10 * (osdata[7] & 0xf) );
|
||||
// Serial.print(":");
|
||||
// Serial.print((osdata[5] >> 4) + 10 * (osdata[6] & 0xf));
|
||||
// Serial.print(":");
|
||||
// Serial.print((osdata[4] >> 4) + 10 * (osdata[5] & 0xf));
|
||||
// Serial.println();
|
||||
// break;
|
||||
//}
|
||||
// ==================================================================================
|
||||
// eac0 Ampere meter: cent-a-meter, OWL CM113, Electrisave
|
||||
// ==================================================================================
|
||||
if(id == 0xeac0) {
|
||||
//Serial.println("UNKNOWN LAYOUT");
|
||||
// ----------------------------------
|
||||
// Output
|
||||
// ----------------------------------
|
||||
sprintf(pbuffer, "20;%02X;", PKSequenceNumber++); // Node and packet number
|
||||
Serial.print( pbuffer );
|
||||
// ----------------------------------
|
||||
Serial.print("Oregon Unknown;"); // Label
|
||||
for(byte x=0; x<13;x++) {
|
||||
Serial.print( osdata[x],HEX );
|
||||
Serial.print((" "));
|
||||
}
|
||||
Serial.println(";");
|
||||
return success;
|
||||
} else
|
||||
// ==================================================================================
|
||||
// 0x1a* / 0x2a* 0x3a** Power meter: OWL CM119
|
||||
// ==================================================================================
|
||||
// ==================================================================================
|
||||
// 1a99 Anemometer: WGTR800
|
||||
// WIND + TEMP + HUM + CRC
|
||||
// ==================================================================================
|
||||
if(id == 0x1a99) { // Wind sensor
|
||||
//Serial.println("UNKNOWN LAYOUT");
|
||||
// ----------------------------------
|
||||
// Output
|
||||
// ----------------------------------
|
||||
sprintf(pbuffer, "20;%02X;", PKSequenceNumber++); // Node and packet number
|
||||
Serial.print( pbuffer );
|
||||
// ----------------------------------
|
||||
Serial.print("Oregon Unknown;"); // Label
|
||||
for(byte x=0; x<13;x++) {
|
||||
Serial.print( osdata[x],HEX );
|
||||
Serial.print((" "));
|
||||
}
|
||||
Serial.println(";");
|
||||
return success;
|
||||
} else
|
||||
// ==================================================================================
|
||||
if( (id&0xf00)==0xA00 ) { // Wind sensor
|
||||
// ----------------------------------
|
||||
// Output
|
||||
// ----------------------------------
|
||||
sprintf(pbuffer, "20;%02X;", PKSequenceNumber++); // Node and packet number
|
||||
Serial.print( pbuffer );
|
||||
// ----------------------------------
|
||||
Serial.print("Oregon Unknown;"); // Label
|
||||
for(byte x=0; x<13;x++) {
|
||||
Serial.print( osdata[x],HEX );
|
||||
Serial.print((" "));
|
||||
}
|
||||
Serial.println(";");
|
||||
}
|
||||
// ==================================================================================
|
||||
RawSignal.Repeats=true; // suppress repeats of the same RF packet
|
||||
RawSignal.Number=0;
|
||||
success = true;
|
||||
#endif // PLUGIN_048_CORE
|
||||
return success;
|
||||
}
|
|
@ -0,0 +1,58 @@
|
|||
//#######################################################################################################
|
||||
//## This Plugin is only for use with the RFLink software package ##
|
||||
//## Plugin-254: Signal Analyzer ##
|
||||
//#######################################################################################################
|
||||
/*********************************************************************************************\
|
||||
* This plugin shows pulse lengths that have been received on RF and have not been decoded by
|
||||
* one of the other plugins. The primary use of this plugin is to provide an easy way to debug and
|
||||
* analyse currently unsupported RF signals
|
||||
*
|
||||
* Author : StuntTeam
|
||||
* 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!
|
||||
***********************************************************************************************
|
||||
* Technical description:
|
||||
* This plugin just outputs unsupported RF packets, use this plugin to find signals from new devices
|
||||
* Even if you do not know what to do with the data yourself you might want to share your data so
|
||||
* others can analyse it.
|
||||
\*********************************************************************************************/
|
||||
#ifdef PLUGIN_254
|
||||
boolean Plugin_254(byte function, char *string) {
|
||||
if (QRFDebug==true) { // debug is on?
|
||||
if(RawSignal.Number<26)return false; // make sure the packet is long enough to have a meaning
|
||||
// ----------------------------------
|
||||
// Output
|
||||
// ----------------------------------
|
||||
sprintf(pbuffer, "20;%02X;", PKSequenceNumber++); // Node and packet number
|
||||
Serial.print( pbuffer );
|
||||
// ----------------------------------
|
||||
Serial.print(F("DEBUG;Pulses=")); // debug data
|
||||
Serial.print(RawSignal.Number); // print number of pulses
|
||||
Serial.print(F(";Pulses(uSec)=")); // print pulse durations
|
||||
//PrintHex8(RawSignal.Pulses+1,RawSignal.Number-1);
|
||||
PrintHex8(RawSignal.Pulses+1,RawSignal.Number);
|
||||
} else {
|
||||
if (RFUDebug==false) return false; // debug is on?
|
||||
if(RawSignal.Number<26)return false; // make sure the packet is long enough to have a meaning
|
||||
// ----------------------------------
|
||||
// Output
|
||||
// ----------------------------------
|
||||
sprintf(pbuffer, "20;%02X;", PKSequenceNumber++); // Node and packet number
|
||||
Serial.print( pbuffer );
|
||||
// ----------------------------------
|
||||
Serial.print(F("DEBUG;Pulses=")); // debug data
|
||||
Serial.print(RawSignal.Number); // print number of pulses
|
||||
Serial.print(F(";Pulses(uSec)=")); // print pulse durations
|
||||
//for(int x=1;x<RawSignal.Number;x++) {
|
||||
for(int x=1;x<RawSignal.Number+1;x++) {
|
||||
Serial.print(RawSignal.Pulses[x]*RAWSIGNAL_SAMPLE_RATE);
|
||||
//if (x < RawSignal.Number-1) Serial.write(',');
|
||||
if (x < RawSignal.Number) Serial.write(',');
|
||||
}
|
||||
}
|
||||
Serial.println(";");
|
||||
RawSignal.Number=0; // Last plugin, kill packet
|
||||
return true; // stop processing
|
||||
}
|
||||
#endif // PLUGIN_254
|
|
@ -0,0 +1,28 @@
|
|||
// *********************************************************************************************************************************
|
||||
// * Arduino project "Nodo RadioFrequencyLink aka Nodo RFLink Version 1.1"
|
||||
// * © Copyright 2015 StuntTeam - NodoRFLink
|
||||
// * Portions © Copyright 2010..2015 Paul Tonkes (original Nodo 3.7 code)
|
||||
// *
|
||||
// * Nodo RadioFrequencyLink aka Nodo RFLink Version 1.1
|
||||
// *
|
||||
// ********************************************************************************************************************************
|
||||
// * This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License
|
||||
// * as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.
|
||||
// * 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 received a copy of the GNU General Public License along with this program in file 'COPYING.TXT'.
|
||||
// * For more information on GPL licensing: http://www.gnu.org/licenses
|
||||
// ********************************************************************************************************************************
|
||||
|
||||
// ================================================================================================================================
|
||||
// Supply the full path to the RFLink files in the define below
|
||||
//
|
||||
// Geef in onderstaande "define" regel het volledige pad op waar de .ino bestanden zich bevinden die je nu geopend hebt.
|
||||
// ================================================================================================================================
|
||||
|
||||
#define SKETCH_PATH D:\arduino\RFLink
|
||||
|
||||
// ================================================================================================================================
|
||||
// IMPORTANT NOTE: This code only runs on an Arduino MEGA !!!!!!!!!!!!!!!!!!!!!! It was designed that way for various reasons.
|
||||
// ================================================================================================================================
|
||||
|
|
@ -0,0 +1,119 @@
|
|||
/*********************************************************************************************/
|
||||
boolean ScanEvent(void) { // Deze routine maakt deel uit van de hoofdloop en wordt iedere 125uSec. doorlopen
|
||||
unsigned long Timer=millis()+SCAN_HIGH_TIME;
|
||||
|
||||
while(Timer>millis() || RepeatingTimer>millis()) {
|
||||
if (FetchSignal(PIN_RF_RX_DATA,HIGH)) { // RF: *** data start ***
|
||||
if ( PluginRXCall(0,0) ) { // Check all plugins to see which plugin can handle the received signal.
|
||||
RepeatingTimer=millis()+SIGNAL_REPEAT_TIME;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}// while
|
||||
return false;
|
||||
}
|
||||
/**********************************************************************************************\
|
||||
* Haal de pulsen en plaats in buffer.
|
||||
* bij de TSOP1738 is in rust is de uitgang hoog. StateSignal moet LOW zijn
|
||||
* bij de 433RX is in rust is de uitgang laag. StateSignal moet HIGH zijn
|
||||
*
|
||||
\*********************************************************************************************/
|
||||
const unsigned long LoopsPerMilli=345;
|
||||
const unsigned long Overhead=0;
|
||||
|
||||
// Because this is a time critical routine, we use global variables so that the variables
|
||||
// do not need to be initialized at each function call.
|
||||
int RawCodeLength=0;
|
||||
unsigned long PulseLength=0L;
|
||||
unsigned long numloops=0L;
|
||||
unsigned long maxloops=0L;
|
||||
|
||||
boolean Ftoggle=false;
|
||||
uint8_t Fbit=0;
|
||||
uint8_t Fport=0;
|
||||
uint8_t FstateMask=0;
|
||||
/*********************************************************************************************/
|
||||
boolean FetchSignal(byte DataPin, boolean StateSignal) {
|
||||
uint8_t Fbit = digitalPinToBitMask(DataPin);
|
||||
uint8_t Fport = digitalPinToPort(DataPin);
|
||||
uint8_t FstateMask = (StateSignal ? Fbit : 0);
|
||||
|
||||
if ((*portInputRegister(Fport) & Fbit) == FstateMask) { // Als er signaal is
|
||||
// Als het een herhalend signaal is, dan is de kans groot dat we binnen hele korte tijd weer in deze
|
||||
// routine terugkomen en dan midden in de volgende herhaling terecht komen. Daarom wordt er in dit
|
||||
// geval gewacht totdat de pulsen voorbij zijn en we met het capturen van data beginnen na een korte
|
||||
// rust tussen de signalen.Op deze wijze wordt het aantal zinloze captures teruggebracht.
|
||||
if (RawSignal.Time) { // Eerst een snelle check, want dit bevindt zich in een tijdkritisch deel...
|
||||
if (RawSignal.Repeats && (RawSignal.Time+SIGNAL_REPEAT_TIME)>millis()) { // ...want deze check duurt enkele micro's langer!
|
||||
PulseLength=micros()+SIGNAL_TIMEOUT*1000; // delay
|
||||
while ((RawSignal.Time+SIGNAL_REPEAT_TIME)>millis() && PulseLength>micros())
|
||||
if ((*portInputRegister(Fport) & Fbit) == FstateMask)
|
||||
PulseLength=micros()+SIGNAL_TIMEOUT*1000;
|
||||
while((RawSignal.Time+SIGNAL_REPEAT_TIME)>millis() && (*portInputRegister(Fport) & Fbit) != FstateMask);
|
||||
}
|
||||
}
|
||||
RawCodeLength=1; // Start at 1 for legacy reasons. Element 0 can be used to pass special information like plugin number etc.
|
||||
Ftoggle=false;
|
||||
maxloops = (SIGNAL_TIMEOUT * LoopsPerMilli);
|
||||
do{ // read the pulses in microseconds and place them in temporary buffer RawSignal
|
||||
numloops = 0;
|
||||
while (((*portInputRegister(Fport) & Fbit) == FstateMask) ^ Ftoggle) // while() loop *A*
|
||||
if (numloops++ == maxloops) break; // timeout
|
||||
PulseLength=((numloops + Overhead)* 1000) / LoopsPerMilli; // Contains pulslength in microseconds
|
||||
if (PulseLength<MIN_PULSE_LENGTH) break; // Pulse length too short
|
||||
Ftoggle=!Ftoggle;
|
||||
RawSignal.Pulses[RawCodeLength++]=PulseLength/(unsigned long)(RAWSIGNAL_SAMPLE_RATE); // store in RawSignal !!!!
|
||||
} while (RawCodeLength<RAW_BUFFER_SIZE && numloops<=maxloops); // For as long as there is space in the buffer, no timeout etc.
|
||||
if (RawCodeLength>=MIN_RAW_PULSES) {
|
||||
RawSignal.Repeats=0; // no repeats
|
||||
RawSignal.Multiply=RAWSIGNAL_SAMPLE_RATE; // sample size.
|
||||
RawSignal.Number=RawCodeLength-1; // Number of received pulse times (pulsen *2)
|
||||
RawSignal.Pulses[RawSignal.Number+1]=0; // Last element contains the timeout.
|
||||
RawSignal.Time=millis(); // Time the RF packet was received (to keep track of retransmits
|
||||
return true;
|
||||
} else {
|
||||
RawSignal.Number=0;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
/*********************************************************************************************/
|
||||
// RFLink Board specific: Generate a short pulse to switch the Aurel Transceiver from TX to RX mode.
|
||||
void RFLinkHW( void ) {
|
||||
delayMicroseconds(36);
|
||||
digitalWrite(PIN_BSF_0,LOW);
|
||||
delayMicroseconds(16);
|
||||
digitalWrite(PIN_BSF_0,HIGH);
|
||||
return;
|
||||
}
|
||||
/*********************************************************************************************\
|
||||
* Send rawsignal buffer to RF * DEPRICATED * DO NOT USE *
|
||||
\*********************************************************************************************/
|
||||
void RawSendRF(void) { // * DEPRICATED * DO NOT USE *
|
||||
int x;
|
||||
digitalWrite(PIN_RF_RX_VCC,LOW); // Spanning naar de RF ontvanger uit om interferentie met de zender te voorkomen.
|
||||
digitalWrite(PIN_RF_TX_VCC,HIGH); // zet de 433Mhz zender aan
|
||||
delayMicroseconds(TRANSMITTER_STABLE_DELAY); // short delay to let the transmitter become stable (Note: Aurel RTX MID needs 500µS/0,5ms)
|
||||
|
||||
RawSignal.Pulses[RawSignal.Number]=1; // due to a bug in Arduino 1.0.1
|
||||
|
||||
for(byte y=0; y<RawSignal.Repeats; y++) { // herhaal verzenden RF code
|
||||
x=1;
|
||||
noInterrupts();
|
||||
while(x<RawSignal.Number) {
|
||||
digitalWrite(PIN_RF_TX_DATA,HIGH);
|
||||
delayMicroseconds(RawSignal.Pulses[x++]*RawSignal.Multiply-5); // min een kleine correctie
|
||||
digitalWrite(PIN_RF_TX_DATA,LOW);
|
||||
delayMicroseconds(RawSignal.Pulses[x++]*RawSignal.Multiply-7); // min een kleine correctie
|
||||
}
|
||||
interrupts();
|
||||
if (y+1 < RawSignal.Repeats) delay(RawSignal.Delay); // Delay buiten het gebied waar de interrupts zijn uitgeschakeld! Anders werkt deze funktie niet.
|
||||
}
|
||||
|
||||
delayMicroseconds(TRANSMITTER_STABLE_DELAY); // short delay to let the transmitter become stable (Note: Aurel RTX MID needs 500µS/0,5ms)
|
||||
digitalWrite(PIN_RF_TX_VCC,LOW); // zet de 433Mhz zender weer uit
|
||||
digitalWrite(PIN_RF_RX_VCC,HIGH); // Spanning naar de RF ontvanger weer aan.
|
||||
RFLinkHW();
|
||||
}
|
||||
/*********************************************************************************************/
|
||||
|
|
@ -0,0 +1,40 @@
|
|||
! ============================================================================
|
||||
! Only for educational purposes, this source is not be synchronized with the
|
||||
! latest release!
|
||||
! For normal operation, use the RFLink Loader that includes the latest release
|
||||
! This source code tree is made available so that you can develop your own plugins
|
||||
! ============================================================================
|
||||
|
||||
Please note that the RFLink Gateway is a freeware project.
|
||||
Stuntteam is not making money in any way.
|
||||
This means that there are no unlimited funds to purchase test devices,
|
||||
it also means the project has to rely on you, the user, to send debug data.
|
||||
|
||||
If you want to contribute to this project, you can send a donation which is more than welcome (see www.nemcon.nl/blog2 donation button),
|
||||
or help with sending debug data of unsupported devices (you can even write and contribute plugins and/or code fixes),
|
||||
or donate the device that you would like to see supported.
|
||||
|
||||
Right now we are looking for some older remotes and/or switches.
|
||||
Like for example: Impuls, Ikea Koppla, Powerfix, Blyss, Home Confort, Conrad, Kambrook, Everflourish
|
||||
For the implementation of the planned 2.4Ghz support we could use some simple MySensor devices.
|
||||
For the implementation of the planned 868Mhz support we could use some devices as well.
|
||||
If you have anything that you do not use, send a mail to frankzirrone@gmail.com
|
||||
Thanks in advance!
|
||||
|
||||
------------------------
|
||||
Synology NAS:
|
||||
If you want to use RFLink with a Synology NAS you can use:
|
||||
- an Arduino Mega clone based on CH340 USB/serial chip
|
||||
In all other cases:
|
||||
- connect a 10 uF capacitor between reset and ground on the Arduino.
|
||||
Simply stick the pins of the capacitor in the power connector socket.
|
||||
When you want to update the firmware of the Arduino, remove the capacitor and reconnect it when done.
|
||||
For details about the Domoticz Synology package check out: http://www.jadahl.com
|
||||
------------------------
|
||||
RFlink via Network Connection:
|
||||
It is possible to use RFlink via a network connection using ser2net.
|
||||
------------------------
|
||||
You can now use the RFLink Gateway with the following home automation software:
|
||||
Domoticz
|
||||
Jeedom
|
||||
------------------------
|
Loading…
Reference in New Issue