mirror of https://github.com/arendst/Tasmota.git
Initial release of RF transceiving
Initial release of RF transceiving using library RcSwitch (#2702)
This commit is contained in:
parent
d9b9eeef1f
commit
f2b04092f8
|
@ -0,0 +1,17 @@
|
|||
# Mac stuff
|
||||
.DS_Store
|
||||
|
||||
# Compiled Object files
|
||||
*.slo
|
||||
*.lo
|
||||
*.o
|
||||
|
||||
# Compiled Dynamic libraries
|
||||
*.so
|
||||
*.dylib
|
||||
|
||||
# Compiled Static libraries
|
||||
*.lai
|
||||
*.la
|
||||
*.a
|
||||
|
|
@ -0,0 +1,69 @@
|
|||
language: c
|
||||
python:
|
||||
- "2.7"
|
||||
|
||||
# Cache PlatformIO packages using Travis CI container-based infrastructure
|
||||
cache:
|
||||
pip: true
|
||||
directories:
|
||||
- "~/.platformio"
|
||||
|
||||
env:
|
||||
- >
|
||||
PLATFORMIO_CI_SRC=$PWD/examples/Webserver
|
||||
ARDUINOIDE_CI_SRC=$PLATFORMIO_CI_SRC/Webserver.ino
|
||||
BOARDS="--board=diecimilaatmega328 --board=uno --board=esp01"
|
||||
- >
|
||||
PLATFORMIO_CI_SRC=$PWD/examples/ReceiveDemo_Simple
|
||||
ARDUINOIDE_CI_SRC=$PLATFORMIO_CI_SRC/ReceiveDemo_Simple.ino
|
||||
BOARDS="--board=diecimilaatmega328 --board=uno --board=esp01"
|
||||
- >
|
||||
PLATFORMIO_CI_SRC=$PWD/examples/TypeC_Intertechno
|
||||
ARDUINOIDE_CI_SRC=$PLATFORMIO_CI_SRC/TypeC_Intertechno.ino
|
||||
BOARDS="--board=diecimilaatmega328 --board=uno --board=esp01 --board=attiny25 --board=attiny24"
|
||||
- >
|
||||
PLATFORMIO_CI_SRC=$PWD/examples/TypeD_REV
|
||||
ARDUINOIDE_CI_SRC=$PLATFORMIO_CI_SRC/TypeD_REV.ino
|
||||
BOARDS="--board=diecimilaatmega328 --board=uno --board=esp01 --board=attiny25 --board=attiny24"
|
||||
- >
|
||||
PLATFORMIO_CI_SRC=$PWD/examples/TypeA_WithDIPSwitches
|
||||
ARDUINOIDE_CI_SRC=$PLATFORMIO_CI_SRC/TypeA_WithDIPSwitches.ino
|
||||
BOARDS="--board=diecimilaatmega328 --board=uno --board=esp01 --board=attiny25 --board=attiny24"
|
||||
- >
|
||||
PLATFORMIO_CI_SRC=$PWD/examples/TypeA_WithDIPSwitches_Lightweight
|
||||
ARDUINOIDE_CI_SRC=$PLATFORMIO_CI_SRC/TypeA_WithDIPSwitches_Lightweight.ino
|
||||
BOARDS="--board=diecimilaatmega328 --board=uno --board=esp01 --board=attiny25 --board=attiny24"
|
||||
- >
|
||||
PLATFORMIO_CI_SRC=$PWD/examples/TypeB_WithRotaryOrSlidingSwitches
|
||||
ARDUINOIDE_CI_SRC=$PLATFORMIO_CI_SRC/TypeB_WithRotaryOrSlidingSwitches.ino
|
||||
BOARDS="--board=diecimilaatmega328 --board=uno --board=esp01 --board=attiny25 --board=attiny24"
|
||||
- >
|
||||
PLATFORMIO_CI_SRC=$PWD/examples/SendDemo
|
||||
ARDUINOIDE_CI_SRC=$PLATFORMIO_CI_SRC/SendDemo.ino
|
||||
BOARDS="--board=diecimilaatmega328 --board=uno --board=esp01"
|
||||
- >
|
||||
PLATFORMIO_CI_SRC=$PWD/examples/ReceiveDemo_Advanced
|
||||
ARDUINOIDE_CI_SRC=$PLATFORMIO_CI_SRC/ReceiveDemo_Advanced.ino
|
||||
BOARDS="--board=diecimilaatmega328 --board=uno --board=esp01"
|
||||
|
||||
before_install:
|
||||
# Arduino IDE
|
||||
- "/sbin/start-stop-daemon --start --quiet --pidfile /tmp/custom_xvfb_1.pid --make-pidfile --background --exec /usr/bin/Xvfb -- :1 -ac -screen 0 1280x1024x16"
|
||||
- sleep 3
|
||||
- export DISPLAY=:1.0
|
||||
- wget http://downloads.arduino.cc/arduino-1.6.9-linux64.tar.xz
|
||||
- tar xf arduino-1.6.9-linux64.tar.xz
|
||||
- sudo mv arduino-1.6.9 /usr/local/share/arduino
|
||||
- sudo ln -s /usr/local/share/arduino/arduino /usr/local/bin/arduino
|
||||
|
||||
install:
|
||||
# Arduino IDE
|
||||
- ln -s $PWD /usr/local/share/arduino/libraries/rc-switch
|
||||
# PlatformIO
|
||||
- sudo pip install -U platformio
|
||||
|
||||
script:
|
||||
# Arduino IDE
|
||||
- arduino --verify --board arduino:avr:uno ${ARDUINOIDE_CI_SRC}
|
||||
# PlatformIO
|
||||
- platformio ci --lib="." ${BOARDS}
|
|
@ -0,0 +1,701 @@
|
|||
/*
|
||||
RCSwitch - Arduino libary for remote control outlet switches
|
||||
Copyright (c) 2011 Suat Özgür. All right reserved.
|
||||
|
||||
Contributors:
|
||||
- Andre Koehler / info(at)tomate-online(dot)de
|
||||
- Gordeev Andrey Vladimirovich / gordeev(at)openpyro(dot)com
|
||||
- Skineffect / http://forum.ardumote.com/viewtopic.php?f=2&t=46
|
||||
- Dominik Fischer / dom_fischer(at)web(dot)de
|
||||
- Frank Oltmanns / <first name>.<last name>(at)gmail(dot)com
|
||||
- Andreas Steinel / A.<lastname>(at)gmail(dot)com
|
||||
- Max Horn / max(at)quendi(dot)de
|
||||
- Robert ter Vehn / <first name>.<last name>(at)gmail(dot)com
|
||||
- Johann Richard / <first name>.<last name>(at)gmail(dot)com
|
||||
- Vlad Gheorghe / <first name>.<last name>(at)gmail(dot)com https://github.com/vgheo
|
||||
|
||||
Project home: https://github.com/sui77/rc-switch/
|
||||
|
||||
This library is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Lesser General Public
|
||||
License as published by the Free Software Foundation; either
|
||||
version 2.1 of the License, or (at your option) any later version.
|
||||
|
||||
This library 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
|
||||
Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public
|
||||
License along with this library; if not, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
#include "RCSwitch.h"
|
||||
|
||||
#ifdef RaspberryPi
|
||||
// PROGMEM and _P functions are for AVR based microprocessors,
|
||||
// so we must normalize these for the ARM processor:
|
||||
#define PROGMEM
|
||||
#define memcpy_P(dest, src, num) memcpy((dest), (src), (num))
|
||||
#endif
|
||||
|
||||
#if defined(ESP8266) || defined(ESP32)
|
||||
// interrupt handler and related code must be in RAM on ESP8266,
|
||||
// according to issue #46.
|
||||
#define RECEIVE_ATTR ICACHE_RAM_ATTR
|
||||
#else
|
||||
#define RECEIVE_ATTR
|
||||
#endif
|
||||
|
||||
|
||||
/* Format for protocol definitions:
|
||||
* {pulselength, Sync bit, "0" bit, "1" bit}
|
||||
*
|
||||
* pulselength: pulse length in microseconds, e.g. 350
|
||||
* Sync bit: {1, 31} means 1 high pulse and 31 low pulses
|
||||
* (perceived as a 31*pulselength long pulse, total length of sync bit is
|
||||
* 32*pulselength microseconds), i.e:
|
||||
* _
|
||||
* | |_______________________________ (don't count the vertical bars)
|
||||
* "0" bit: waveform for a data bit of value "0", {1, 3} means 1 high pulse
|
||||
* and 3 low pulses, total length (1+3)*pulselength, i.e:
|
||||
* _
|
||||
* | |___
|
||||
* "1" bit: waveform for a data bit of value "1", e.g. {3,1}:
|
||||
* ___
|
||||
* | |_
|
||||
*
|
||||
* These are combined to form Tri-State bits when sending or receiving codes.
|
||||
*/
|
||||
#if defined(ESP8266) || defined(ESP32)
|
||||
static const RCSwitch::Protocol proto[] = {
|
||||
#else
|
||||
static const RCSwitch::Protocol PROGMEM proto[] = {
|
||||
#endif
|
||||
{ 350, { 1, 31 }, { 1, 3 }, { 3, 1 }, false }, // protocol 1
|
||||
{ 650, { 1, 10 }, { 1, 2 }, { 2, 1 }, false }, // protocol 2
|
||||
{ 100, { 30, 71 }, { 4, 11 }, { 9, 6 }, false }, // protocol 3
|
||||
{ 380, { 1, 6 }, { 1, 3 }, { 3, 1 }, false }, // protocol 4
|
||||
{ 500, { 6, 14 }, { 1, 2 }, { 2, 1 }, false }, // protocol 5
|
||||
{ 450, { 23, 1 }, { 1, 2 }, { 2, 1 }, true }, // protocol 6 (HT6P20B)
|
||||
{ 150, { 2, 62 }, { 1, 6 }, { 6, 1 }, false } // protocol 7 (HS2303-PT, i. e. used in AUKEY Remote)
|
||||
};
|
||||
|
||||
enum {
|
||||
numProto = sizeof(proto) / sizeof(proto[0])
|
||||
};
|
||||
|
||||
#if not defined( RCSwitchDisableReceiving )
|
||||
volatile unsigned long RCSwitch::nReceivedValue = 0;
|
||||
volatile unsigned int RCSwitch::nReceivedBitlength = 0;
|
||||
volatile unsigned int RCSwitch::nReceivedDelay = 0;
|
||||
volatile unsigned int RCSwitch::nReceivedProtocol = 0;
|
||||
int RCSwitch::nReceiveTolerance = 60;
|
||||
const unsigned int RCSwitch::nSeparationLimit = 4300;
|
||||
// separationLimit: minimum microseconds between received codes, closer codes are ignored.
|
||||
// according to discussion on issue #14 it might be more suitable to set the separation
|
||||
// limit to the same time as the 'low' part of the sync signal for the current protocol.
|
||||
unsigned int RCSwitch::timings[RCSWITCH_MAX_CHANGES];
|
||||
#endif
|
||||
|
||||
RCSwitch::RCSwitch() {
|
||||
this->nTransmitterPin = -1;
|
||||
this->setRepeatTransmit(10);
|
||||
this->setProtocol(1);
|
||||
#if not defined( RCSwitchDisableReceiving )
|
||||
this->nReceiverInterrupt = -1;
|
||||
this->setReceiveTolerance(60);
|
||||
RCSwitch::nReceivedValue = 0;
|
||||
#endif
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the protocol to send.
|
||||
*/
|
||||
void RCSwitch::setProtocol(Protocol protocol) {
|
||||
this->protocol = protocol;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the protocol to send, from a list of predefined protocols
|
||||
*/
|
||||
void RCSwitch::setProtocol(int nProtocol) {
|
||||
if (nProtocol < 1 || nProtocol > numProto) {
|
||||
nProtocol = 1; // TODO: trigger an error, e.g. "bad protocol" ???
|
||||
}
|
||||
#if defined(ESP8266) || defined(ESP32)
|
||||
this->protocol = proto[nProtocol-1];
|
||||
#else
|
||||
memcpy_P(&this->protocol, &proto[nProtocol-1], sizeof(Protocol));
|
||||
#endif
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the protocol to send with pulse length in microseconds.
|
||||
*/
|
||||
void RCSwitch::setProtocol(int nProtocol, int nPulseLength) {
|
||||
setProtocol(nProtocol);
|
||||
this->setPulseLength(nPulseLength);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Sets pulse length in microseconds
|
||||
*/
|
||||
void RCSwitch::setPulseLength(int nPulseLength) {
|
||||
this->protocol.pulseLength = nPulseLength;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets Repeat Transmits
|
||||
*/
|
||||
void RCSwitch::setRepeatTransmit(int nRepeatTransmit) {
|
||||
this->nRepeatTransmit = nRepeatTransmit;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set Receiving Tolerance
|
||||
*/
|
||||
#if not defined( RCSwitchDisableReceiving )
|
||||
void RCSwitch::setReceiveTolerance(int nPercent) {
|
||||
RCSwitch::nReceiveTolerance = nPercent;
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
/**
|
||||
* Enable transmissions
|
||||
*
|
||||
* @param nTransmitterPin Arduino Pin to which the sender is connected to
|
||||
*/
|
||||
void RCSwitch::enableTransmit(int nTransmitterPin) {
|
||||
this->nTransmitterPin = nTransmitterPin;
|
||||
pinMode(this->nTransmitterPin, OUTPUT);
|
||||
}
|
||||
|
||||
/**
|
||||
* Disable transmissions
|
||||
*/
|
||||
void RCSwitch::disableTransmit() {
|
||||
this->nTransmitterPin = -1;
|
||||
}
|
||||
|
||||
/**
|
||||
* Switch a remote switch on (Type D REV)
|
||||
*
|
||||
* @param sGroup Code of the switch group (A,B,C,D)
|
||||
* @param nDevice Number of the switch itself (1..3)
|
||||
*/
|
||||
void RCSwitch::switchOn(char sGroup, int nDevice) {
|
||||
this->sendTriState( this->getCodeWordD(sGroup, nDevice, true) );
|
||||
}
|
||||
|
||||
/**
|
||||
* Switch a remote switch off (Type D REV)
|
||||
*
|
||||
* @param sGroup Code of the switch group (A,B,C,D)
|
||||
* @param nDevice Number of the switch itself (1..3)
|
||||
*/
|
||||
void RCSwitch::switchOff(char sGroup, int nDevice) {
|
||||
this->sendTriState( this->getCodeWordD(sGroup, nDevice, false) );
|
||||
}
|
||||
|
||||
/**
|
||||
* Switch a remote switch on (Type C Intertechno)
|
||||
*
|
||||
* @param sFamily Familycode (a..f)
|
||||
* @param nGroup Number of group (1..4)
|
||||
* @param nDevice Number of device (1..4)
|
||||
*/
|
||||
void RCSwitch::switchOn(char sFamily, int nGroup, int nDevice) {
|
||||
this->sendTriState( this->getCodeWordC(sFamily, nGroup, nDevice, true) );
|
||||
}
|
||||
|
||||
/**
|
||||
* Switch a remote switch off (Type C Intertechno)
|
||||
*
|
||||
* @param sFamily Familycode (a..f)
|
||||
* @param nGroup Number of group (1..4)
|
||||
* @param nDevice Number of device (1..4)
|
||||
*/
|
||||
void RCSwitch::switchOff(char sFamily, int nGroup, int nDevice) {
|
||||
this->sendTriState( this->getCodeWordC(sFamily, nGroup, nDevice, false) );
|
||||
}
|
||||
|
||||
/**
|
||||
* Switch a remote switch on (Type B with two rotary/sliding switches)
|
||||
*
|
||||
* @param nAddressCode Number of the switch group (1..4)
|
||||
* @param nChannelCode Number of the switch itself (1..4)
|
||||
*/
|
||||
void RCSwitch::switchOn(int nAddressCode, int nChannelCode) {
|
||||
this->sendTriState( this->getCodeWordB(nAddressCode, nChannelCode, true) );
|
||||
}
|
||||
|
||||
/**
|
||||
* Switch a remote switch off (Type B with two rotary/sliding switches)
|
||||
*
|
||||
* @param nAddressCode Number of the switch group (1..4)
|
||||
* @param nChannelCode Number of the switch itself (1..4)
|
||||
*/
|
||||
void RCSwitch::switchOff(int nAddressCode, int nChannelCode) {
|
||||
this->sendTriState( this->getCodeWordB(nAddressCode, nChannelCode, false) );
|
||||
}
|
||||
|
||||
/**
|
||||
* Deprecated, use switchOn(const char* sGroup, const char* sDevice) instead!
|
||||
* Switch a remote switch on (Type A with 10 pole DIP switches)
|
||||
*
|
||||
* @param sGroup Code of the switch group (refers to DIP switches 1..5 where "1" = on and "0" = off, if all DIP switches are on it's "11111")
|
||||
* @param nChannelCode Number of the switch itself (1..5)
|
||||
*/
|
||||
void RCSwitch::switchOn(const char* sGroup, int nChannel) {
|
||||
const char* code[6] = { "00000", "10000", "01000", "00100", "00010", "00001" };
|
||||
this->switchOn(sGroup, code[nChannel]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Deprecated, use switchOff(const char* sGroup, const char* sDevice) instead!
|
||||
* Switch a remote switch off (Type A with 10 pole DIP switches)
|
||||
*
|
||||
* @param sGroup Code of the switch group (refers to DIP switches 1..5 where "1" = on and "0" = off, if all DIP switches are on it's "11111")
|
||||
* @param nChannelCode Number of the switch itself (1..5)
|
||||
*/
|
||||
void RCSwitch::switchOff(const char* sGroup, int nChannel) {
|
||||
const char* code[6] = { "00000", "10000", "01000", "00100", "00010", "00001" };
|
||||
this->switchOff(sGroup, code[nChannel]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Switch a remote switch on (Type A with 10 pole DIP switches)
|
||||
*
|
||||
* @param sGroup Code of the switch group (refers to DIP switches 1..5 where "1" = on and "0" = off, if all DIP switches are on it's "11111")
|
||||
* @param sDevice Code of the switch device (refers to DIP switches 6..10 (A..E) where "1" = on and "0" = off, if all DIP switches are on it's "11111")
|
||||
*/
|
||||
void RCSwitch::switchOn(const char* sGroup, const char* sDevice) {
|
||||
this->sendTriState( this->getCodeWordA(sGroup, sDevice, true) );
|
||||
}
|
||||
|
||||
/**
|
||||
* Switch a remote switch off (Type A with 10 pole DIP switches)
|
||||
*
|
||||
* @param sGroup Code of the switch group (refers to DIP switches 1..5 where "1" = on and "0" = off, if all DIP switches are on it's "11111")
|
||||
* @param sDevice Code of the switch device (refers to DIP switches 6..10 (A..E) where "1" = on and "0" = off, if all DIP switches are on it's "11111")
|
||||
*/
|
||||
void RCSwitch::switchOff(const char* sGroup, const char* sDevice) {
|
||||
this->sendTriState( this->getCodeWordA(sGroup, sDevice, false) );
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Returns a char[13], representing the code word to be send.
|
||||
*
|
||||
*/
|
||||
char* RCSwitch::getCodeWordA(const char* sGroup, const char* sDevice, bool bStatus) {
|
||||
static char sReturn[13];
|
||||
int nReturnPos = 0;
|
||||
|
||||
for (int i = 0; i < 5; i++) {
|
||||
sReturn[nReturnPos++] = (sGroup[i] == '0') ? 'F' : '0';
|
||||
}
|
||||
|
||||
for (int i = 0; i < 5; i++) {
|
||||
sReturn[nReturnPos++] = (sDevice[i] == '0') ? 'F' : '0';
|
||||
}
|
||||
|
||||
sReturn[nReturnPos++] = bStatus ? '0' : 'F';
|
||||
sReturn[nReturnPos++] = bStatus ? 'F' : '0';
|
||||
|
||||
sReturn[nReturnPos] = '\0';
|
||||
return sReturn;
|
||||
}
|
||||
|
||||
/**
|
||||
* Encoding for type B switches with two rotary/sliding switches.
|
||||
*
|
||||
* The code word is a tristate word and with following bit pattern:
|
||||
*
|
||||
* +-----------------------------+-----------------------------+----------+------------+
|
||||
* | 4 bits address | 4 bits address | 3 bits | 1 bit |
|
||||
* | switch group | switch number | not used | on / off |
|
||||
* | 1=0FFF 2=F0FF 3=FF0F 4=FFF0 | 1=0FFF 2=F0FF 3=FF0F 4=FFF0 | FFF | on=F off=0 |
|
||||
* +-----------------------------+-----------------------------+----------+------------+
|
||||
*
|
||||
* @param nAddressCode Number of the switch group (1..4)
|
||||
* @param nChannelCode Number of the switch itself (1..4)
|
||||
* @param bStatus Whether to switch on (true) or off (false)
|
||||
*
|
||||
* @return char[13], representing a tristate code word of length 12
|
||||
*/
|
||||
char* RCSwitch::getCodeWordB(int nAddressCode, int nChannelCode, bool bStatus) {
|
||||
static char sReturn[13];
|
||||
int nReturnPos = 0;
|
||||
|
||||
if (nAddressCode < 1 || nAddressCode > 4 || nChannelCode < 1 || nChannelCode > 4) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
for (int i = 1; i <= 4; i++) {
|
||||
sReturn[nReturnPos++] = (nAddressCode == i) ? '0' : 'F';
|
||||
}
|
||||
|
||||
for (int i = 1; i <= 4; i++) {
|
||||
sReturn[nReturnPos++] = (nChannelCode == i) ? '0' : 'F';
|
||||
}
|
||||
|
||||
sReturn[nReturnPos++] = 'F';
|
||||
sReturn[nReturnPos++] = 'F';
|
||||
sReturn[nReturnPos++] = 'F';
|
||||
|
||||
sReturn[nReturnPos++] = bStatus ? 'F' : '0';
|
||||
|
||||
sReturn[nReturnPos] = '\0';
|
||||
return sReturn;
|
||||
}
|
||||
|
||||
/**
|
||||
* Like getCodeWord (Type C = Intertechno)
|
||||
*/
|
||||
char* RCSwitch::getCodeWordC(char sFamily, int nGroup, int nDevice, bool bStatus) {
|
||||
static char sReturn[13];
|
||||
int nReturnPos = 0;
|
||||
|
||||
int nFamily = (int)sFamily - 'a';
|
||||
if ( nFamily < 0 || nFamily > 15 || nGroup < 1 || nGroup > 4 || nDevice < 1 || nDevice > 4) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
// encode the family into four bits
|
||||
sReturn[nReturnPos++] = (nFamily & 1) ? 'F' : '0';
|
||||
sReturn[nReturnPos++] = (nFamily & 2) ? 'F' : '0';
|
||||
sReturn[nReturnPos++] = (nFamily & 4) ? 'F' : '0';
|
||||
sReturn[nReturnPos++] = (nFamily & 8) ? 'F' : '0';
|
||||
|
||||
// encode the device and group
|
||||
sReturn[nReturnPos++] = ((nDevice-1) & 1) ? 'F' : '0';
|
||||
sReturn[nReturnPos++] = ((nDevice-1) & 2) ? 'F' : '0';
|
||||
sReturn[nReturnPos++] = ((nGroup-1) & 1) ? 'F' : '0';
|
||||
sReturn[nReturnPos++] = ((nGroup-1) & 2) ? 'F' : '0';
|
||||
|
||||
// encode the status code
|
||||
sReturn[nReturnPos++] = '0';
|
||||
sReturn[nReturnPos++] = 'F';
|
||||
sReturn[nReturnPos++] = 'F';
|
||||
sReturn[nReturnPos++] = bStatus ? 'F' : '0';
|
||||
|
||||
sReturn[nReturnPos] = '\0';
|
||||
return sReturn;
|
||||
}
|
||||
|
||||
/**
|
||||
* Encoding for the REV Switch Type
|
||||
*
|
||||
* The code word is a tristate word and with following bit pattern:
|
||||
*
|
||||
* +-----------------------------+-------------------+----------+--------------+
|
||||
* | 4 bits address | 3 bits address | 3 bits | 2 bits |
|
||||
* | switch group | device number | not used | on / off |
|
||||
* | A=1FFF B=F1FF C=FF1F D=FFF1 | 1=0FF 2=F0F 3=FF0 | 000 | on=10 off=01 |
|
||||
* +-----------------------------+-------------------+----------+--------------+
|
||||
*
|
||||
* Source: http://www.the-intruder.net/funksteckdosen-von-rev-uber-arduino-ansteuern/
|
||||
*
|
||||
* @param sGroup Name of the switch group (A..D, resp. a..d)
|
||||
* @param nDevice Number of the switch itself (1..3)
|
||||
* @param bStatus Whether to switch on (true) or off (false)
|
||||
*
|
||||
* @return char[13], representing a tristate code word of length 12
|
||||
*/
|
||||
char* RCSwitch::getCodeWordD(char sGroup, int nDevice, bool bStatus) {
|
||||
static char sReturn[13];
|
||||
int nReturnPos = 0;
|
||||
|
||||
// sGroup must be one of the letters in "abcdABCD"
|
||||
int nGroup = (sGroup >= 'a') ? (int)sGroup - 'a' : (int)sGroup - 'A';
|
||||
if ( nGroup < 0 || nGroup > 3 || nDevice < 1 || nDevice > 3) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
for (int i = 0; i < 4; i++) {
|
||||
sReturn[nReturnPos++] = (nGroup == i) ? '1' : 'F';
|
||||
}
|
||||
|
||||
for (int i = 1; i <= 3; i++) {
|
||||
sReturn[nReturnPos++] = (nDevice == i) ? '1' : 'F';
|
||||
}
|
||||
|
||||
sReturn[nReturnPos++] = '0';
|
||||
sReturn[nReturnPos++] = '0';
|
||||
sReturn[nReturnPos++] = '0';
|
||||
|
||||
sReturn[nReturnPos++] = bStatus ? '1' : '0';
|
||||
sReturn[nReturnPos++] = bStatus ? '0' : '1';
|
||||
|
||||
sReturn[nReturnPos] = '\0';
|
||||
return sReturn;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param sCodeWord a tristate code word consisting of the letter 0, 1, F
|
||||
*/
|
||||
void RCSwitch::sendTriState(const char* sCodeWord) {
|
||||
// turn the tristate code word into the corresponding bit pattern, then send it
|
||||
unsigned long code = 0;
|
||||
unsigned int length = 0;
|
||||
for (const char* p = sCodeWord; *p; p++) {
|
||||
code <<= 2L;
|
||||
switch (*p) {
|
||||
case '0':
|
||||
// bit pattern 00
|
||||
break;
|
||||
case 'F':
|
||||
// bit pattern 01
|
||||
code |= 1L;
|
||||
break;
|
||||
case '1':
|
||||
// bit pattern 11
|
||||
code |= 3L;
|
||||
break;
|
||||
}
|
||||
length += 2;
|
||||
}
|
||||
this->send(code, length);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param sCodeWord a binary code word consisting of the letter 0, 1
|
||||
*/
|
||||
void RCSwitch::send(const char* sCodeWord) {
|
||||
// turn the tristate code word into the corresponding bit pattern, then send it
|
||||
unsigned long code = 0;
|
||||
unsigned int length = 0;
|
||||
for (const char* p = sCodeWord; *p; p++) {
|
||||
code <<= 1L;
|
||||
if (*p != '0')
|
||||
code |= 1L;
|
||||
length++;
|
||||
}
|
||||
this->send(code, length);
|
||||
}
|
||||
|
||||
/**
|
||||
* Transmit the first 'length' bits of the integer 'code'. The
|
||||
* bits are sent from MSB to LSB, i.e., first the bit at position length-1,
|
||||
* then the bit at position length-2, and so on, till finally the bit at position 0.
|
||||
*/
|
||||
void RCSwitch::send(unsigned long code, unsigned int length) {
|
||||
if (this->nTransmitterPin == -1)
|
||||
return;
|
||||
|
||||
#if not defined( RCSwitchDisableReceiving )
|
||||
// make sure the receiver is disabled while we transmit
|
||||
int nReceiverInterrupt_backup = nReceiverInterrupt;
|
||||
if (nReceiverInterrupt_backup != -1) {
|
||||
this->disableReceive();
|
||||
}
|
||||
#endif
|
||||
|
||||
for (int nRepeat = 0; nRepeat < nRepeatTransmit; nRepeat++) {
|
||||
for (int i = length-1; i >= 0; i--) {
|
||||
if (code & (1L << i))
|
||||
this->transmit(protocol.one);
|
||||
else
|
||||
this->transmit(protocol.zero);
|
||||
}
|
||||
this->transmit(protocol.syncFactor);
|
||||
}
|
||||
|
||||
// Disable transmit after sending (i.e., for inverted protocols)
|
||||
digitalWrite(this->nTransmitterPin, LOW);
|
||||
|
||||
#if not defined( RCSwitchDisableReceiving )
|
||||
// enable receiver again if we just disabled it
|
||||
if (nReceiverInterrupt_backup != -1) {
|
||||
this->enableReceive(nReceiverInterrupt_backup);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
/**
|
||||
* Transmit a single high-low pulse.
|
||||
*/
|
||||
void RCSwitch::transmit(HighLow pulses) {
|
||||
uint8_t firstLogicLevel = (this->protocol.invertedSignal) ? LOW : HIGH;
|
||||
uint8_t secondLogicLevel = (this->protocol.invertedSignal) ? HIGH : LOW;
|
||||
|
||||
digitalWrite(this->nTransmitterPin, firstLogicLevel);
|
||||
delayMicroseconds( this->protocol.pulseLength * pulses.high);
|
||||
digitalWrite(this->nTransmitterPin, secondLogicLevel);
|
||||
delayMicroseconds( this->protocol.pulseLength * pulses.low);
|
||||
}
|
||||
|
||||
|
||||
#if not defined( RCSwitchDisableReceiving )
|
||||
/**
|
||||
* Enable receiving data
|
||||
*/
|
||||
void RCSwitch::enableReceive(int interrupt) {
|
||||
this->nReceiverInterrupt = interrupt;
|
||||
this->enableReceive();
|
||||
}
|
||||
|
||||
void RCSwitch::enableReceive() {
|
||||
if (this->nReceiverInterrupt != -1) {
|
||||
RCSwitch::nReceivedValue = 0;
|
||||
RCSwitch::nReceivedBitlength = 0;
|
||||
#if defined(RaspberryPi) // Raspberry Pi
|
||||
wiringPiISR(this->nReceiverInterrupt, INT_EDGE_BOTH, &handleInterrupt);
|
||||
#else // Arduino
|
||||
attachInterrupt(this->nReceiverInterrupt, handleInterrupt, CHANGE);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Disable receiving data
|
||||
*/
|
||||
void RCSwitch::disableReceive() {
|
||||
#if not defined(RaspberryPi) // Arduino
|
||||
detachInterrupt(this->nReceiverInterrupt);
|
||||
#endif // For Raspberry Pi (wiringPi) you can't unregister the ISR
|
||||
this->nReceiverInterrupt = -1;
|
||||
}
|
||||
|
||||
bool RCSwitch::available() {
|
||||
return RCSwitch::nReceivedValue != 0;
|
||||
}
|
||||
|
||||
void RCSwitch::resetAvailable() {
|
||||
RCSwitch::nReceivedValue = 0;
|
||||
}
|
||||
|
||||
unsigned long RCSwitch::getReceivedValue() {
|
||||
return RCSwitch::nReceivedValue;
|
||||
}
|
||||
|
||||
unsigned int RCSwitch::getReceivedBitlength() {
|
||||
return RCSwitch::nReceivedBitlength;
|
||||
}
|
||||
|
||||
unsigned int RCSwitch::getReceivedDelay() {
|
||||
return RCSwitch::nReceivedDelay;
|
||||
}
|
||||
|
||||
unsigned int RCSwitch::getReceivedProtocol() {
|
||||
return RCSwitch::nReceivedProtocol;
|
||||
}
|
||||
|
||||
unsigned int* RCSwitch::getReceivedRawdata() {
|
||||
return RCSwitch::timings;
|
||||
}
|
||||
|
||||
/* helper function for the receiveProtocol method */
|
||||
static inline unsigned int diff(int A, int B) {
|
||||
return abs(A - B);
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
bool RECEIVE_ATTR RCSwitch::receiveProtocol(const int p, unsigned int changeCount) {
|
||||
#if defined(ESP8266) || defined(ESP32)
|
||||
const Protocol &pro = proto[p-1];
|
||||
#else
|
||||
Protocol pro;
|
||||
memcpy_P(&pro, &proto[p-1], sizeof(Protocol));
|
||||
#endif
|
||||
|
||||
unsigned long code = 0;
|
||||
//Assuming the longer pulse length is the pulse captured in timings[0]
|
||||
const unsigned int syncLengthInPulses = ((pro.syncFactor.low) > (pro.syncFactor.high)) ? (pro.syncFactor.low) : (pro.syncFactor.high);
|
||||
const unsigned int delay = RCSwitch::timings[0] / syncLengthInPulses;
|
||||
const unsigned int delayTolerance = delay * RCSwitch::nReceiveTolerance / 100;
|
||||
|
||||
/* For protocols that start low, the sync period looks like
|
||||
* _________
|
||||
* _____________| |XXXXXXXXXXXX|
|
||||
*
|
||||
* |--1st dur--|-2nd dur-|-Start data-|
|
||||
*
|
||||
* The 3rd saved duration starts the data.
|
||||
*
|
||||
* For protocols that start high, the sync period looks like
|
||||
*
|
||||
* ______________
|
||||
* | |____________|XXXXXXXXXXXXX|
|
||||
*
|
||||
* |-filtered out-|--1st dur--|--Start data--|
|
||||
*
|
||||
* The 2nd saved duration starts the data
|
||||
*/
|
||||
const unsigned int firstDataTiming = (pro.invertedSignal) ? (2) : (1);
|
||||
|
||||
for (unsigned int i = firstDataTiming; i < changeCount - 1; i += 2) {
|
||||
code <<= 1;
|
||||
if (diff(RCSwitch::timings[i], delay * pro.zero.high) < delayTolerance &&
|
||||
diff(RCSwitch::timings[i + 1], delay * pro.zero.low) < delayTolerance) {
|
||||
// zero
|
||||
} else if (diff(RCSwitch::timings[i], delay * pro.one.high) < delayTolerance &&
|
||||
diff(RCSwitch::timings[i + 1], delay * pro.one.low) < delayTolerance) {
|
||||
// one
|
||||
code |= 1;
|
||||
} else {
|
||||
// Failed
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
if (changeCount > 7) { // ignore very short transmissions: no device sends them, so this must be noise
|
||||
RCSwitch::nReceivedValue = code;
|
||||
RCSwitch::nReceivedBitlength = (changeCount - 1) / 2;
|
||||
RCSwitch::nReceivedDelay = delay;
|
||||
RCSwitch::nReceivedProtocol = p;
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
void RECEIVE_ATTR RCSwitch::handleInterrupt() {
|
||||
|
||||
static unsigned int changeCount = 0;
|
||||
static unsigned long lastTime = 0;
|
||||
static unsigned int repeatCount = 0;
|
||||
|
||||
const long time = micros();
|
||||
const unsigned int duration = time - lastTime;
|
||||
|
||||
if (duration > RCSwitch::nSeparationLimit) {
|
||||
// A long stretch without signal level change occurred. This could
|
||||
// be the gap between two transmission.
|
||||
if (diff(duration, RCSwitch::timings[0]) < 200) {
|
||||
// This long signal is close in length to the long signal which
|
||||
// started the previously recorded timings; this suggests that
|
||||
// it may indeed by a a gap between two transmissions (we assume
|
||||
// here that a sender will send the signal multiple times,
|
||||
// with roughly the same gap between them).
|
||||
repeatCount++;
|
||||
if (repeatCount == 2) {
|
||||
for(unsigned int i = 1; i <= numProto; i++) {
|
||||
if (receiveProtocol(i, changeCount)) {
|
||||
// receive succeeded for protocol i
|
||||
break;
|
||||
}
|
||||
}
|
||||
repeatCount = 0;
|
||||
}
|
||||
}
|
||||
changeCount = 0;
|
||||
}
|
||||
|
||||
// detect overflow
|
||||
if (changeCount >= RCSWITCH_MAX_CHANGES) {
|
||||
changeCount = 0;
|
||||
repeatCount = 0;
|
||||
}
|
||||
|
||||
RCSwitch::timings[changeCount++] = duration;
|
||||
lastTime = time;
|
||||
}
|
||||
#endif
|
|
@ -0,0 +1,184 @@
|
|||
/*
|
||||
RCSwitch - Arduino libary for remote control outlet switches
|
||||
Copyright (c) 2011 Suat Özgür. All right reserved.
|
||||
|
||||
Contributors:
|
||||
- Andre Koehler / info(at)tomate-online(dot)de
|
||||
- Gordeev Andrey Vladimirovich / gordeev(at)openpyro(dot)com
|
||||
- Skineffect / http://forum.ardumote.com/viewtopic.php?f=2&t=46
|
||||
- Dominik Fischer / dom_fischer(at)web(dot)de
|
||||
- Frank Oltmanns / <first name>.<last name>(at)gmail(dot)com
|
||||
- Max Horn / max(at)quendi(dot)de
|
||||
- Robert ter Vehn / <first name>.<last name>(at)gmail(dot)com
|
||||
|
||||
Project home: https://github.com/sui77/rc-switch/
|
||||
|
||||
This library is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Lesser General Public
|
||||
License as published by the Free Software Foundation; either
|
||||
version 2.1 of the License, or (at your option) any later version.
|
||||
|
||||
This library 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
|
||||
Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public
|
||||
License along with this library; if not, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
#ifndef _RCSwitch_h
|
||||
#define _RCSwitch_h
|
||||
|
||||
#if defined(ARDUINO) && ARDUINO >= 100
|
||||
#include "Arduino.h"
|
||||
#elif defined(ENERGIA) // LaunchPad, FraunchPad and StellarPad specific
|
||||
#include "Energia.h"
|
||||
#elif defined(RPI) // Raspberry Pi
|
||||
#define RaspberryPi
|
||||
|
||||
// Include libraries for RPi:
|
||||
#include <string.h> /* memcpy */
|
||||
#include <stdlib.h> /* abs */
|
||||
#include <wiringPi.h>
|
||||
#elif defined(SPARK)
|
||||
#include "application.h"
|
||||
#else
|
||||
#include "WProgram.h"
|
||||
#endif
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
|
||||
// At least for the ATTiny X4/X5, receiving has to be disabled due to
|
||||
// missing libm depencies (udivmodhi4)
|
||||
#if defined( __AVR_ATtinyX5__ ) or defined ( __AVR_ATtinyX4__ )
|
||||
#define RCSwitchDisableReceiving
|
||||
#endif
|
||||
|
||||
// Number of maximum high/Low changes per packet.
|
||||
// We can handle up to (unsigned long) => 32 bit * 2 H/L changes per bit + 2 for sync
|
||||
#define RCSWITCH_MAX_CHANGES 67
|
||||
|
||||
class RCSwitch {
|
||||
|
||||
public:
|
||||
RCSwitch();
|
||||
|
||||
void switchOn(int nGroupNumber, int nSwitchNumber);
|
||||
void switchOff(int nGroupNumber, int nSwitchNumber);
|
||||
void switchOn(const char* sGroup, int nSwitchNumber);
|
||||
void switchOff(const char* sGroup, int nSwitchNumber);
|
||||
void switchOn(char sFamily, int nGroup, int nDevice);
|
||||
void switchOff(char sFamily, int nGroup, int nDevice);
|
||||
void switchOn(const char* sGroup, const char* sDevice);
|
||||
void switchOff(const char* sGroup, const char* sDevice);
|
||||
void switchOn(char sGroup, int nDevice);
|
||||
void switchOff(char sGroup, int nDevice);
|
||||
|
||||
void sendTriState(const char* sCodeWord);
|
||||
void send(unsigned long code, unsigned int length);
|
||||
void send(const char* sCodeWord);
|
||||
|
||||
#if not defined( RCSwitchDisableReceiving )
|
||||
void enableReceive(int interrupt);
|
||||
void enableReceive();
|
||||
void disableReceive();
|
||||
bool available();
|
||||
void resetAvailable();
|
||||
|
||||
unsigned long getReceivedValue();
|
||||
unsigned int getReceivedBitlength();
|
||||
unsigned int getReceivedDelay();
|
||||
unsigned int getReceivedProtocol();
|
||||
unsigned int* getReceivedRawdata();
|
||||
#endif
|
||||
|
||||
void enableTransmit(int nTransmitterPin);
|
||||
void disableTransmit();
|
||||
void setPulseLength(int nPulseLength);
|
||||
void setRepeatTransmit(int nRepeatTransmit);
|
||||
#if not defined( RCSwitchDisableReceiving )
|
||||
void setReceiveTolerance(int nPercent);
|
||||
#endif
|
||||
|
||||
/**
|
||||
* Description of a single pule, which consists of a high signal
|
||||
* whose duration is "high" times the base pulse length, followed
|
||||
* by a low signal lasting "low" times the base pulse length.
|
||||
* Thus, the pulse overall lasts (high+low)*pulseLength
|
||||
*/
|
||||
struct HighLow {
|
||||
uint8_t high;
|
||||
uint8_t low;
|
||||
};
|
||||
|
||||
/**
|
||||
* A "protocol" describes how zero and one bits are encoded into high/low
|
||||
* pulses.
|
||||
*/
|
||||
struct Protocol {
|
||||
/** base pulse length in microseconds, e.g. 350 */
|
||||
uint16_t pulseLength;
|
||||
|
||||
HighLow syncFactor;
|
||||
HighLow zero;
|
||||
HighLow one;
|
||||
|
||||
/**
|
||||
* If true, interchange high and low logic levels in all transmissions.
|
||||
*
|
||||
* By default, RCSwitch assumes that any signals it sends or receives
|
||||
* can be broken down into pulses which start with a high signal level,
|
||||
* followed by a a low signal level. This is e.g. the case for the
|
||||
* popular PT 2260 encoder chip, and thus many switches out there.
|
||||
*
|
||||
* But some devices do it the other way around, and start with a low
|
||||
* signal level, followed by a high signal level, e.g. the HT6P20B. To
|
||||
* accommodate this, one can set invertedSignal to true, which causes
|
||||
* RCSwitch to change how it interprets any HighLow struct FOO: It will
|
||||
* then assume transmissions start with a low signal lasting
|
||||
* FOO.high*pulseLength microseconds, followed by a high signal lasting
|
||||
* FOO.low*pulseLength microseconds.
|
||||
*/
|
||||
bool invertedSignal;
|
||||
};
|
||||
|
||||
void setProtocol(Protocol protocol);
|
||||
void setProtocol(int nProtocol);
|
||||
void setProtocol(int nProtocol, int nPulseLength);
|
||||
|
||||
private:
|
||||
char* getCodeWordA(const char* sGroup, const char* sDevice, bool bStatus);
|
||||
char* getCodeWordB(int nGroupNumber, int nSwitchNumber, bool bStatus);
|
||||
char* getCodeWordC(char sFamily, int nGroup, int nDevice, bool bStatus);
|
||||
char* getCodeWordD(char group, int nDevice, bool bStatus);
|
||||
void transmit(HighLow pulses);
|
||||
|
||||
#if not defined( RCSwitchDisableReceiving )
|
||||
static void handleInterrupt();
|
||||
static bool receiveProtocol(const int p, unsigned int changeCount);
|
||||
int nReceiverInterrupt;
|
||||
#endif
|
||||
int nTransmitterPin;
|
||||
int nRepeatTransmit;
|
||||
|
||||
Protocol protocol;
|
||||
|
||||
#if not defined( RCSwitchDisableReceiving )
|
||||
static int nReceiveTolerance;
|
||||
volatile static unsigned long nReceivedValue;
|
||||
volatile static unsigned int nReceivedBitlength;
|
||||
volatile static unsigned int nReceivedDelay;
|
||||
volatile static unsigned int nReceivedProtocol;
|
||||
const static unsigned int nSeparationLimit;
|
||||
/*
|
||||
* timings[0] contains sync timing, followed by a number of bits
|
||||
*/
|
||||
static unsigned int timings[RCSWITCH_MAX_CHANGES];
|
||||
#endif
|
||||
|
||||
|
||||
};
|
||||
|
||||
#endif
|
|
@ -0,0 +1,41 @@
|
|||
# rc-switch
|
||||
[![Build Status](https://travis-ci.org/sui77/rc-switch.svg?branch=master)](https://travis-ci.org/sui77/rc-switch)
|
||||
|
||||
Use your Arduino or Raspberry Pi to operate remote radio controlled devices
|
||||
|
||||
## Download
|
||||
https://github.com/sui77/rc-switch/releases/latest
|
||||
|
||||
rc-switch is also listed in the arduino library manager.
|
||||
|
||||
## Wiki
|
||||
https://github.com/sui77/rc-switch/wiki
|
||||
|
||||
## Info
|
||||
### Send RC codes
|
||||
|
||||
Use your Arduino or Raspberry Pi to operate remote radio controlled devices.
|
||||
This will most likely work with all popular low cost power outlet sockets. If
|
||||
yours doesn't work, you might need to adjust the pulse length.
|
||||
|
||||
All you need is a Arduino or Raspberry Pi, a 315/433MHz AM transmitter and one
|
||||
or more devices with one of the supported chipsets:
|
||||
|
||||
- SC5262 / SC5272
|
||||
- HX2262 / HX2272
|
||||
- PT2262 / PT2272
|
||||
- EV1527 / RT1527 / FP1527 / HS1527
|
||||
- Intertechno outlets
|
||||
- HT6P20X
|
||||
|
||||
### Receive and decode RC codes
|
||||
|
||||
Find out what codes your remote is sending. Use your remote to control your
|
||||
Arduino.
|
||||
|
||||
All you need is an Arduino, a 315/433MHz AM receiver (altough there is no
|
||||
instruction yet, yes it is possible to hack an existing device) and a remote
|
||||
hand set.
|
||||
|
||||
For the Raspberry Pi, clone the https://github.com/ninjablocks/433Utils project to
|
||||
compile a sniffer tool and transmission commands.
|
|
@ -0,0 +1,24 @@
|
|||
/*
|
||||
Example for receiving
|
||||
|
||||
https://github.com/sui77/rc-switch/
|
||||
|
||||
If you want to visualize a telegram copy the raw data and
|
||||
paste it into http://test.sui.li/oszi/
|
||||
*/
|
||||
|
||||
#include <RCSwitch.h>
|
||||
|
||||
RCSwitch mySwitch = RCSwitch();
|
||||
|
||||
void setup() {
|
||||
Serial.begin(9600);
|
||||
mySwitch.enableReceive(0); // Receiver on interrupt 0 => that is pin #2
|
||||
}
|
||||
|
||||
void loop() {
|
||||
if (mySwitch.available()) {
|
||||
output(mySwitch.getReceivedValue(), mySwitch.getReceivedBitlength(), mySwitch.getReceivedDelay(), mySwitch.getReceivedRawdata(),mySwitch.getReceivedProtocol());
|
||||
mySwitch.resetAvailable();
|
||||
}
|
||||
}
|
|
@ -0,0 +1,70 @@
|
|||
static const char* bin2tristate(const char* bin);
|
||||
static char * dec2binWzerofill(unsigned long Dec, unsigned int bitLength);
|
||||
|
||||
void output(unsigned long decimal, unsigned int length, unsigned int delay, unsigned int* raw, unsigned int protocol) {
|
||||
|
||||
const char* b = dec2binWzerofill(decimal, length);
|
||||
Serial.print("Decimal: ");
|
||||
Serial.print(decimal);
|
||||
Serial.print(" (");
|
||||
Serial.print( length );
|
||||
Serial.print("Bit) Binary: ");
|
||||
Serial.print( b );
|
||||
Serial.print(" Tri-State: ");
|
||||
Serial.print( bin2tristate( b) );
|
||||
Serial.print(" PulseLength: ");
|
||||
Serial.print(delay);
|
||||
Serial.print(" microseconds");
|
||||
Serial.print(" Protocol: ");
|
||||
Serial.println(protocol);
|
||||
|
||||
Serial.print("Raw data: ");
|
||||
for (unsigned int i=0; i<= length*2; i++) {
|
||||
Serial.print(raw[i]);
|
||||
Serial.print(",");
|
||||
}
|
||||
Serial.println();
|
||||
Serial.println();
|
||||
}
|
||||
|
||||
static const char* bin2tristate(const char* bin) {
|
||||
static char returnValue[50];
|
||||
int pos = 0;
|
||||
int pos2 = 0;
|
||||
while (bin[pos]!='\0' && bin[pos+1]!='\0') {
|
||||
if (bin[pos]=='0' && bin[pos+1]=='0') {
|
||||
returnValue[pos2] = '0';
|
||||
} else if (bin[pos]=='1' && bin[pos+1]=='1') {
|
||||
returnValue[pos2] = '1';
|
||||
} else if (bin[pos]=='0' && bin[pos+1]=='1') {
|
||||
returnValue[pos2] = 'F';
|
||||
} else {
|
||||
return "not applicable";
|
||||
}
|
||||
pos = pos+2;
|
||||
pos2++;
|
||||
}
|
||||
returnValue[pos2] = '\0';
|
||||
return returnValue;
|
||||
}
|
||||
|
||||
static char * dec2binWzerofill(unsigned long Dec, unsigned int bitLength) {
|
||||
static char bin[64];
|
||||
unsigned int i=0;
|
||||
|
||||
while (Dec > 0) {
|
||||
bin[32+i++] = ((Dec & 1) > 0) ? '1' : '0';
|
||||
Dec = Dec >> 1;
|
||||
}
|
||||
|
||||
for (unsigned int j = 0; j< bitLength; j++) {
|
||||
if (j >= bitLength - i) {
|
||||
bin[j] = bin[ 31 + i - (j - (bitLength - i)) ];
|
||||
} else {
|
||||
bin[j] = '0';
|
||||
}
|
||||
}
|
||||
bin[bitLength] = '\0';
|
||||
|
||||
return bin;
|
||||
}
|
|
@ -0,0 +1,29 @@
|
|||
/*
|
||||
Simple example for receiving
|
||||
|
||||
https://github.com/sui77/rc-switch/
|
||||
*/
|
||||
|
||||
#include <RCSwitch.h>
|
||||
|
||||
RCSwitch mySwitch = RCSwitch();
|
||||
|
||||
void setup() {
|
||||
Serial.begin(9600);
|
||||
mySwitch.enableReceive(0); // Receiver on interrupt 0 => that is pin #2
|
||||
}
|
||||
|
||||
void loop() {
|
||||
if (mySwitch.available()) {
|
||||
|
||||
Serial.print("Received ");
|
||||
Serial.print( mySwitch.getReceivedValue() );
|
||||
Serial.print(" / ");
|
||||
Serial.print( mySwitch.getReceivedBitlength() );
|
||||
Serial.print("bit ");
|
||||
Serial.print("Protocol: ");
|
||||
Serial.println( mySwitch.getReceivedProtocol() );
|
||||
|
||||
mySwitch.resetAvailable();
|
||||
}
|
||||
}
|
|
@ -0,0 +1,57 @@
|
|||
/*
|
||||
Example for different sending methods
|
||||
|
||||
https://github.com/sui77/rc-switch/
|
||||
|
||||
*/
|
||||
|
||||
#include <RCSwitch.h>
|
||||
|
||||
RCSwitch mySwitch = RCSwitch();
|
||||
|
||||
void setup() {
|
||||
|
||||
Serial.begin(9600);
|
||||
|
||||
// Transmitter is connected to Arduino Pin #10
|
||||
mySwitch.enableTransmit(10);
|
||||
|
||||
// Optional set protocol (default is 1, will work for most outlets)
|
||||
// mySwitch.setProtocol(2);
|
||||
|
||||
// Optional set pulse length.
|
||||
// mySwitch.setPulseLength(320);
|
||||
|
||||
// Optional set number of transmission repetitions.
|
||||
// mySwitch.setRepeatTransmit(15);
|
||||
|
||||
}
|
||||
|
||||
void loop() {
|
||||
|
||||
/* See Example: TypeA_WithDIPSwitches */
|
||||
mySwitch.switchOn("11111", "00010");
|
||||
delay(1000);
|
||||
mySwitch.switchOff("11111", "00010");
|
||||
delay(1000);
|
||||
|
||||
/* Same switch as above, but using decimal code */
|
||||
mySwitch.send(5393, 24);
|
||||
delay(1000);
|
||||
mySwitch.send(5396, 24);
|
||||
delay(1000);
|
||||
|
||||
/* Same switch as above, but using binary code */
|
||||
mySwitch.send("000000000001010100010001");
|
||||
delay(1000);
|
||||
mySwitch.send("000000000001010100010100");
|
||||
delay(1000);
|
||||
|
||||
/* Same switch as above, but tri-state code */
|
||||
mySwitch.sendTriState("00000FFF0F0F");
|
||||
delay(1000);
|
||||
mySwitch.sendTriState("00000FFF0FF0");
|
||||
delay(1000);
|
||||
|
||||
delay(20000);
|
||||
}
|
|
@ -0,0 +1,40 @@
|
|||
/*
|
||||
Example for outlets which are configured with a 10 pole DIP switch.
|
||||
|
||||
https://github.com/sui77/rc-switch/
|
||||
*/
|
||||
|
||||
#include <RCSwitch.h>
|
||||
|
||||
RCSwitch mySwitch = RCSwitch();
|
||||
|
||||
void setup() {
|
||||
|
||||
// Transmitter is connected to Arduino Pin #10
|
||||
mySwitch.enableTransmit(10);
|
||||
|
||||
// Optional set pulse length.
|
||||
// mySwitch.setPulseLength(320);
|
||||
|
||||
}
|
||||
|
||||
void loop() {
|
||||
|
||||
// Switch on:
|
||||
// The first parameter represents the setting of the first 5 DIP switches.
|
||||
// In this example it's ON-ON-OFF-OFF-ON.
|
||||
//
|
||||
// The second parameter represents the setting of the last 5 DIP switches.
|
||||
// In this example the last 5 DIP switches are OFF-ON-OFF-ON-OFF.
|
||||
mySwitch.switchOn("11001", "01010");
|
||||
|
||||
// Wait a second
|
||||
delay(1000);
|
||||
|
||||
// Switch off
|
||||
mySwitch.switchOff("11001", "01010");
|
||||
|
||||
// Wait another second
|
||||
delay(1000);
|
||||
|
||||
}
|
|
@ -0,0 +1,43 @@
|
|||
/*
|
||||
This is a minimal sketch without using the library at all but only works for
|
||||
the 10 pole dip switch sockets. It saves a lot of memory and thus might be
|
||||
very useful to use with ATTinys :)
|
||||
|
||||
https://github.com/sui77/rc-switch/
|
||||
*/
|
||||
|
||||
int RCLpin = 7;
|
||||
|
||||
void setup() {
|
||||
pinMode(RCLpin, OUTPUT);
|
||||
}
|
||||
|
||||
void loop() {
|
||||
RCLswitch(0b010001000001); // DIPs an Steckdose: 0100010000 An:01
|
||||
delay(2000);
|
||||
|
||||
RCLswitch(0b010001000010); // DIPs an Steckdose: 0100010000 Aus:10
|
||||
delay(2000);
|
||||
}
|
||||
|
||||
void RCLswitch(uint16_t code) {
|
||||
for (int nRepeat=0; nRepeat<6; nRepeat++) {
|
||||
for (int i=4; i<16; i++) {
|
||||
RCLtransmit(1,3);
|
||||
if (((code << (i-4)) & 2048) > 0) {
|
||||
RCLtransmit(1,3);
|
||||
} else {
|
||||
RCLtransmit(3,1);
|
||||
}
|
||||
}
|
||||
RCLtransmit(1,31);
|
||||
}
|
||||
}
|
||||
|
||||
void RCLtransmit(int nHighPulses, int nLowPulses) {
|
||||
digitalWrite(RCLpin, HIGH);
|
||||
delayMicroseconds( 350 * nHighPulses);
|
||||
digitalWrite(RCLpin, LOW);
|
||||
delayMicroseconds( 350 * nLowPulses);
|
||||
}
|
||||
|
|
@ -0,0 +1,40 @@
|
|||
/*
|
||||
Example for outlets which are configured with two rotary/sliding switches.
|
||||
|
||||
https://github.com/sui77/rc-switch/
|
||||
*/
|
||||
|
||||
#include <RCSwitch.h>
|
||||
|
||||
RCSwitch mySwitch = RCSwitch();
|
||||
|
||||
void setup() {
|
||||
|
||||
// Transmitter is connected to Arduino Pin #10
|
||||
mySwitch.enableTransmit(10);
|
||||
|
||||
// Optional set pulse length.
|
||||
// mySwitch.setPulseLength(320);
|
||||
|
||||
}
|
||||
|
||||
void loop() {
|
||||
|
||||
// Switch on:
|
||||
// The first parameter represents the setting of the first rotary switch.
|
||||
// In this example it's switched to "1" or "A" or "I".
|
||||
//
|
||||
// The second parameter represents the setting of the second rotary switch.
|
||||
// In this example it's switched to "4" or "D" or "IV".
|
||||
mySwitch.switchOn(1, 4);
|
||||
|
||||
// Wait a second
|
||||
delay(1000);
|
||||
|
||||
// Switch off
|
||||
mySwitch.switchOff(1, 4);
|
||||
|
||||
// Wait another second
|
||||
delay(1000);
|
||||
|
||||
}
|
|
@ -0,0 +1,40 @@
|
|||
/*
|
||||
Example for Intertechno outlets
|
||||
|
||||
https://github.com/sui77/rc-switch/
|
||||
*/
|
||||
|
||||
#include <RCSwitch.h>
|
||||
|
||||
RCSwitch mySwitch = RCSwitch();
|
||||
|
||||
void setup() {
|
||||
|
||||
// Transmitter is connected to Arduino Pin #10
|
||||
mySwitch.enableTransmit(10);
|
||||
|
||||
// Optional set pulse length.
|
||||
// mySwitch.setPulseLength(320);
|
||||
|
||||
}
|
||||
|
||||
void loop() {
|
||||
|
||||
// Switch on:
|
||||
// The first parameter represents the familycode (a, b, c, ... f)
|
||||
// The second parameter represents the group number
|
||||
// The third parameter represents the device number
|
||||
//
|
||||
// In this example it's family 'b', group #3, device #2
|
||||
mySwitch.switchOn('b', 3, 2);
|
||||
|
||||
// Wait a second
|
||||
delay(1000);
|
||||
|
||||
// Switch off
|
||||
mySwitch.switchOff('b', 3, 2);
|
||||
|
||||
// Wait another second
|
||||
delay(1000);
|
||||
|
||||
}
|
|
@ -0,0 +1,41 @@
|
|||
/*
|
||||
Example for REV outlets (e.g. 8342L)
|
||||
|
||||
https://github.com/sui77/rc-switch/
|
||||
|
||||
Need help? http://forum.ardumote.com
|
||||
*/
|
||||
|
||||
#include <RCSwitch.h>
|
||||
|
||||
RCSwitch mySwitch = RCSwitch();
|
||||
|
||||
void setup() {
|
||||
|
||||
// Transmitter is connected to Arduino Pin #10
|
||||
mySwitch.enableTransmit(10);
|
||||
|
||||
// set pulse length.
|
||||
mySwitch.setPulseLength(360);
|
||||
|
||||
}
|
||||
|
||||
void loop() {
|
||||
|
||||
// Switch on:
|
||||
// The first parameter represents the channel (a, b, c, d)
|
||||
// The second parameter represents the device number
|
||||
//
|
||||
// In this example it's family 'd', device #2
|
||||
mySwitch.switchOn('d', 2);
|
||||
|
||||
// Wait a second
|
||||
delay(1000);
|
||||
|
||||
// Switch off
|
||||
mySwitch.switchOff('d', 2);
|
||||
|
||||
// Wait another second
|
||||
delay(1000);
|
||||
|
||||
}
|
|
@ -0,0 +1,154 @@
|
|||
/*
|
||||
A simple RCSwitch/Ethernet/Webserver demo
|
||||
|
||||
https://github.com/sui77/rc-switch/
|
||||
*/
|
||||
|
||||
#include <SPI.h>
|
||||
#include <Ethernet.h>
|
||||
#include <RCSwitch.h>
|
||||
|
||||
// Ethernet configuration
|
||||
uint8_t mac[] = { 0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0xED }; // MAC Address
|
||||
uint8_t ip[] = { 192,168,0, 2 }; // IP Address
|
||||
EthernetServer server(80); // Server Port 80
|
||||
|
||||
// RCSwitch configuration
|
||||
RCSwitch mySwitch = RCSwitch();
|
||||
int RCTransmissionPin = 7;
|
||||
|
||||
// More to do...
|
||||
// You should also modify the processCommand() and
|
||||
// httpResponseHome() functions to fit your needs.
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Setup
|
||||
*/
|
||||
void setup() {
|
||||
Ethernet.begin(mac, ip);
|
||||
server.begin();
|
||||
mySwitch.enableTransmit( RCTransmissionPin );
|
||||
}
|
||||
|
||||
/**
|
||||
* Loop
|
||||
*/
|
||||
void loop() {
|
||||
char* command = httpServer();
|
||||
}
|
||||
|
||||
/**
|
||||
* Command dispatcher
|
||||
*/
|
||||
void processCommand(char* command) {
|
||||
if (strcmp(command, "1-on") == 0) {
|
||||
mySwitch.switchOn(1,1);
|
||||
} else if (strcmp(command, "1-off") == 0) {
|
||||
mySwitch.switchOff(1,1);
|
||||
} else if (strcmp(command, "2-on") == 0) {
|
||||
mySwitch.switchOn(1,2);
|
||||
} else if (strcmp(command, "2-off") == 0) {
|
||||
mySwitch.switchOff(1,2);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* HTTP Response with homepage
|
||||
*/
|
||||
void httpResponseHome(EthernetClient c) {
|
||||
c.println("HTTP/1.1 200 OK");
|
||||
c.println("Content-Type: text/html");
|
||||
c.println();
|
||||
c.println("<html>");
|
||||
c.println("<head>");
|
||||
c.println( "<title>RCSwitch Webserver Demo</title>");
|
||||
c.println( "<style>");
|
||||
c.println( "body { font-family: Arial, sans-serif; font-size:12px; }");
|
||||
c.println( "</style>");
|
||||
c.println("</head>");
|
||||
c.println("<body>");
|
||||
c.println( "<h1>RCSwitch Webserver Demo</h1>");
|
||||
c.println( "<ul>");
|
||||
c.println( "<li><a href=\"./?1-on\">Switch #1 on</a></li>");
|
||||
c.println( "<li><a href=\"./?1-off\">Switch #1 off</a></li>");
|
||||
c.println( "</ul>");
|
||||
c.println( "<ul>");
|
||||
c.println( "<li><a href=\"./?2-on\">Switch #2 on</a></li>");
|
||||
c.println( "<li><a href=\"./?2-off\">Switch #2 off</a></li>");
|
||||
c.println( "</ul>");
|
||||
c.println( "<hr>");
|
||||
c.println( "<a href=\"https://github.com/sui77/rc-switch/\">https://github.com/sui77/rc-switch/</a>");
|
||||
c.println("</body>");
|
||||
c.println("</html>");
|
||||
}
|
||||
|
||||
/**
|
||||
* HTTP Redirect to homepage
|
||||
*/
|
||||
void httpResponseRedirect(EthernetClient c) {
|
||||
c.println("HTTP/1.1 301 Found");
|
||||
c.println("Location: /");
|
||||
c.println();
|
||||
}
|
||||
|
||||
/**
|
||||
* HTTP Response 414 error
|
||||
* Command must not be longer than 30 characters
|
||||
**/
|
||||
void httpResponse414(EthernetClient c) {
|
||||
c.println("HTTP/1.1 414 Request URI too long");
|
||||
c.println("Content-Type: text/plain");
|
||||
c.println();
|
||||
c.println("414 Request URI too long");
|
||||
}
|
||||
|
||||
/**
|
||||
* Process HTTP requests, parse first request header line and
|
||||
* call processCommand with GET query string (everything after
|
||||
* the ? question mark in the URL).
|
||||
*/
|
||||
char* httpServer() {
|
||||
EthernetClient client = server.available();
|
||||
if (client) {
|
||||
char sReturnCommand[32];
|
||||
int nCommandPos=-1;
|
||||
sReturnCommand[0] = '\0';
|
||||
while (client.connected()) {
|
||||
if (client.available()) {
|
||||
char c = client.read();
|
||||
if ((c == '\n') || (c == ' ' && nCommandPos>-1)) {
|
||||
sReturnCommand[nCommandPos] = '\0';
|
||||
if (strcmp(sReturnCommand, "\0") == 0) {
|
||||
httpResponseHome(client);
|
||||
} else {
|
||||
processCommand(sReturnCommand);
|
||||
httpResponseRedirect(client);
|
||||
}
|
||||
break;
|
||||
}
|
||||
if (nCommandPos>-1) {
|
||||
sReturnCommand[nCommandPos++] = c;
|
||||
}
|
||||
if (c == '?' && nCommandPos == -1) {
|
||||
nCommandPos = 0;
|
||||
}
|
||||
}
|
||||
if (nCommandPos > 30) {
|
||||
httpResponse414(client);
|
||||
sReturnCommand[0] = '\0';
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (nCommandPos!=-1) {
|
||||
sReturnCommand[nCommandPos] = '\0';
|
||||
}
|
||||
// give the web browser time to receive the data
|
||||
delay(1);
|
||||
client.stop();
|
||||
|
||||
return sReturnCommand;
|
||||
}
|
||||
return '\0';
|
||||
}
|
|
@ -0,0 +1,57 @@
|
|||
#######################################
|
||||
# Syntax Coloring Map For RCSwitch
|
||||
#######################################
|
||||
|
||||
#######################################
|
||||
# Datatypes (KEYWORD1)
|
||||
#######################################
|
||||
|
||||
RCSwitch KEYWORD1
|
||||
|
||||
#######################################
|
||||
# Methods and Functions (KEYWORD2)
|
||||
#######################################
|
||||
|
||||
##########
|
||||
#SENDS Begin
|
||||
##########
|
||||
switchOn KEYWORD2
|
||||
switchOff KEYWORD2
|
||||
sendTriState KEYWORD2
|
||||
send KEYWORD2
|
||||
##########
|
||||
#SENDS End
|
||||
##########
|
||||
|
||||
##########
|
||||
#RECEIVE Begin
|
||||
##########
|
||||
enableReceive KEYWORD2
|
||||
disableReceive KEYWORD2
|
||||
available KEYWORD2
|
||||
resetAvailable KEYWORD2
|
||||
setReceiveTolerance KEYWORD2
|
||||
getReceivedValue KEYWORD2
|
||||
getReceivedBitlength KEYWORD2
|
||||
getReceivedDelay KEYWORD2
|
||||
getReceivedProtocol KEYWORD2
|
||||
getReceivedRawdata KEYWORD2
|
||||
##########
|
||||
#RECEIVE End
|
||||
##########
|
||||
|
||||
##########
|
||||
#OTHERS Begin
|
||||
##########
|
||||
enableTransmit KEYWORD2
|
||||
disableTransmit KEYWORD2
|
||||
setPulseLength KEYWORD2
|
||||
setProtocol KEYWORD2
|
||||
setRepeatTransmit KEYWORD2
|
||||
##########
|
||||
#OTHERS End
|
||||
##########
|
||||
|
||||
#######################################
|
||||
# Constants (LITERAL1)
|
||||
#######################################
|
|
@ -0,0 +1,21 @@
|
|||
{
|
||||
"name": "rc-switch",
|
||||
"description": "Use your Arduino or Raspberry Pi to operate remote radio controlled devices",
|
||||
"keywords": "rf, radio, wireless",
|
||||
"authors":
|
||||
{
|
||||
"name": "Suat Ozgur"
|
||||
},
|
||||
"repository":
|
||||
{
|
||||
"type": "git",
|
||||
"url": "https://github.com/sui77/rc-switch.git"
|
||||
},
|
||||
"version": "2.6.2",
|
||||
"frameworks": [
|
||||
"arduino",
|
||||
"energia",
|
||||
"wiringpi"
|
||||
],
|
||||
"platforms": "*"
|
||||
}
|
|
@ -0,0 +1,10 @@
|
|||
name=rc-switch
|
||||
version=2.6.2
|
||||
author=sui77
|
||||
maintainer=sui77,fingolfin <noreply@sui.li>
|
||||
sentence=Operate 433/315Mhz devices.
|
||||
paragraph=Use your Arduino, ESP8266/ESP32 or Raspberry Pi to operate remote radio controlled devices. This will most likely work with all popular low cost power outlet sockets.
|
||||
category=Device Control
|
||||
url=https://github.com/sui77/rc-switch
|
||||
architectures=avr,esp8266,esp32
|
||||
includes=RCSwitch.h
|
|
@ -2,6 +2,7 @@
|
|||
* Fix header file execution order by renaming user_config.h to my_user_config.h
|
||||
* Fix invalid JSON floating point result from nan (Not a Number) and inf (Infinity) into null (#4147)
|
||||
* Fix rule mqtt#connected trigger when mqtt is disabled (#4149)
|
||||
* Initial release of RF transceiving using library RcSwitch (#2702)
|
||||
*
|
||||
* 6.2.1.18 20181019
|
||||
* Add more API callbacks and document API.md
|
||||
|
|
|
@ -525,6 +525,8 @@
|
|||
#define D_SENSOR_HX711_SCK "HX711 SCK"
|
||||
#define D_SENSOR_HX711_DAT "HX711 DAT"
|
||||
#define D_SENSOR_TX20_TX "TX20"
|
||||
#define D_SENSOR_RFSEND "RFSend"
|
||||
#define D_SENSOR_RFRECV "RFrecv"
|
||||
|
||||
// Units
|
||||
#define D_UNIT_AMPERE "A"
|
||||
|
|
|
@ -525,6 +525,8 @@
|
|||
#define D_SENSOR_HX711_SCK "HX711 SCK"
|
||||
#define D_SENSOR_HX711_DAT "HX711 DAT"
|
||||
#define D_SENSOR_TX20_TX "TX20"
|
||||
#define D_SENSOR_RFSEND "RFSend"
|
||||
#define D_SENSOR_RFRECV "RFrecv"
|
||||
|
||||
// Units
|
||||
#define D_UNIT_AMPERE "A"
|
||||
|
|
|
@ -525,6 +525,8 @@
|
|||
#define D_SENSOR_HX711_SCK "HX711 SCK"
|
||||
#define D_SENSOR_HX711_DAT "HX711 DAT"
|
||||
#define D_SENSOR_TX20_TX "TX20"
|
||||
#define D_SENSOR_RFSEND "RFSend"
|
||||
#define D_SENSOR_RFRECV "RFrecv"
|
||||
|
||||
// Units
|
||||
#define D_UNIT_AMPERE "A"
|
||||
|
|
|
@ -525,6 +525,8 @@
|
|||
#define D_SENSOR_HX711_SCK "HX711 SCK"
|
||||
#define D_SENSOR_HX711_DAT "HX711 DAT"
|
||||
#define D_SENSOR_TX20_TX "TX20"
|
||||
#define D_SENSOR_RFSEND "RFSend"
|
||||
#define D_SENSOR_RFRECV "RFrecv"
|
||||
|
||||
// Units
|
||||
#define D_UNIT_AMPERE "A"
|
||||
|
|
|
@ -525,6 +525,8 @@
|
|||
#define D_SENSOR_HX711_SCK "HX711 SCK"
|
||||
#define D_SENSOR_HX711_DAT "HX711 DAT"
|
||||
#define D_SENSOR_TX20_TX "TX20"
|
||||
#define D_SENSOR_RFSEND "RFSend"
|
||||
#define D_SENSOR_RFRECV "RFrecv"
|
||||
|
||||
// Units
|
||||
#define D_UNIT_AMPERE "A"
|
||||
|
|
|
@ -525,6 +525,8 @@
|
|||
#define D_SENSOR_HX711_SCK "HX711 SCK"
|
||||
#define D_SENSOR_HX711_DAT "HX711 DAT"
|
||||
#define D_SENSOR_TX20_TX "TX20"
|
||||
#define D_SENSOR_RFSEND "RFSend"
|
||||
#define D_SENSOR_RFRECV "RFrecv"
|
||||
|
||||
// Units
|
||||
#define D_UNIT_AMPERE "A"
|
||||
|
|
|
@ -525,6 +525,8 @@
|
|||
#define D_SENSOR_HX711_SCK "HX711 SCK"
|
||||
#define D_SENSOR_HX711_DAT "HX711 DAT"
|
||||
#define D_SENSOR_TX20_TX "TX20"
|
||||
#define D_SENSOR_RFSEND "RFSend"
|
||||
#define D_SENSOR_RFRECV "RFrecv"
|
||||
|
||||
// Units
|
||||
#define D_UNIT_AMPERE "A"
|
||||
|
|
|
@ -525,6 +525,8 @@
|
|||
#define D_SENSOR_HX711_SCK "HX711 SCK"
|
||||
#define D_SENSOR_HX711_DAT "HX711 DAT"
|
||||
#define D_SENSOR_TX20_TX "TX20"
|
||||
#define D_SENSOR_RFSEND "RFSend"
|
||||
#define D_SENSOR_RFRECV "RFrecv"
|
||||
|
||||
// Units
|
||||
#define D_UNIT_AMPERE "A"
|
||||
|
|
|
@ -525,6 +525,8 @@
|
|||
#define D_SENSOR_HX711_SCK "HX711 SCK"
|
||||
#define D_SENSOR_HX711_DAT "HX711 DAT"
|
||||
#define D_SENSOR_TX20_TX "TX20"
|
||||
#define D_SENSOR_RFSEND "RFSend"
|
||||
#define D_SENSOR_RFRECV "RFrecv"
|
||||
|
||||
// Units
|
||||
#define D_UNIT_AMPERE "A"
|
||||
|
|
|
@ -525,6 +525,8 @@
|
|||
#define D_SENSOR_HX711_SCK "HX711 SCK"
|
||||
#define D_SENSOR_HX711_DAT "HX711 DAT"
|
||||
#define D_SENSOR_TX20_TX "TX20"
|
||||
#define D_SENSOR_RFSEND "RFSend"
|
||||
#define D_SENSOR_RFRECV "RFrecv"
|
||||
|
||||
// Units
|
||||
#define D_UNIT_AMPERE "A"
|
||||
|
|
|
@ -525,6 +525,8 @@
|
|||
#define D_SENSOR_HX711_SCK "HX711 SCK"
|
||||
#define D_SENSOR_HX711_DAT "HX711 DAT"
|
||||
#define D_SENSOR_TX20_TX "TX20"
|
||||
#define D_SENSOR_RFSEND "RFSend"
|
||||
#define D_SENSOR_RFRECV "RFrecv"
|
||||
|
||||
// Units
|
||||
#define D_UNIT_AMPERE "A"
|
||||
|
|
|
@ -525,6 +525,8 @@
|
|||
#define D_SENSOR_HX711_SCK "HX711 SCK"
|
||||
#define D_SENSOR_HX711_DAT "HX711 DAT"
|
||||
#define D_SENSOR_TX20_TX "TX20"
|
||||
#define D_SENSOR_RFSEND "RFSend"
|
||||
#define D_SENSOR_RFRECV "RFrecv"
|
||||
|
||||
// Units
|
||||
#define D_UNIT_AMPERE "A"
|
||||
|
|
|
@ -525,6 +525,8 @@
|
|||
#define D_SENSOR_HX711_SCK "HX711 SCK"
|
||||
#define D_SENSOR_HX711_DAT "HX711 DAT"
|
||||
#define D_SENSOR_TX20_TX "TX20"
|
||||
#define D_SENSOR_RFSEND "RFSend"
|
||||
#define D_SENSOR_RFRECV "RFrecv"
|
||||
|
||||
// Units
|
||||
#define D_UNIT_AMPERE "A"
|
||||
|
|
|
@ -525,6 +525,8 @@
|
|||
#define D_SENSOR_HX711_SCK "HX711 SCK"
|
||||
#define D_SENSOR_HX711_DAT "HX711 DAT"
|
||||
#define D_SENSOR_TX20_TX "TX20"
|
||||
#define D_SENSOR_RFSEND "RFSend"
|
||||
#define D_SENSOR_RFRECV "RFrecv"
|
||||
|
||||
// Units
|
||||
#define D_UNIT_AMPERE "A"
|
||||
|
|
|
@ -525,6 +525,8 @@
|
|||
#define D_SENSOR_HX711_SCK "HX711 SCK"
|
||||
#define D_SENSOR_HX711_DAT "HX711 DAT"
|
||||
#define D_SENSOR_TX20_TX "TX20"
|
||||
#define D_SENSOR_RFSEND "RFSend"
|
||||
#define D_SENSOR_RFRECV "RFrecv"
|
||||
|
||||
// Units
|
||||
#define D_UNIT_AMPERE "А"
|
||||
|
|
|
@ -525,6 +525,8 @@
|
|||
#define D_SENSOR_HX711_SCK "HX711 SCK"
|
||||
#define D_SENSOR_HX711_DAT "HX711 DAT"
|
||||
#define D_SENSOR_TX20_TX "TX20"
|
||||
#define D_SENSOR_RFSEND "RFSend"
|
||||
#define D_SENSOR_RFRECV "RFrecv"
|
||||
|
||||
// Units
|
||||
#define D_UNIT_AMPERE "A"
|
||||
|
|
|
@ -525,6 +525,8 @@
|
|||
#define D_SENSOR_HX711_SCK "HX711 SCK"
|
||||
#define D_SENSOR_HX711_DAT "HX711 DAT"
|
||||
#define D_SENSOR_TX20_TX "TX20"
|
||||
#define D_SENSOR_RFSEND "RFSend"
|
||||
#define D_SENSOR_RFRECV "RFrecv"
|
||||
|
||||
// Units
|
||||
#define D_UNIT_AMPERE "А"
|
||||
|
|
|
@ -525,6 +525,8 @@
|
|||
#define D_SENSOR_HX711_SCK "HX711 SCK"
|
||||
#define D_SENSOR_HX711_DAT "HX711 DAT"
|
||||
#define D_SENSOR_TX20_TX "TX20"
|
||||
#define D_SENSOR_RFSEND "RFSend"
|
||||
#define D_SENSOR_RFRECV "RFrecv"
|
||||
|
||||
// Units
|
||||
#define D_UNIT_AMPERE "安"
|
||||
|
|
|
@ -525,6 +525,8 @@
|
|||
#define D_SENSOR_HX711_SCK "HX711 SCK"
|
||||
#define D_SENSOR_HX711_DAT "HX711 DAT"
|
||||
#define D_SENSOR_TX20_TX "TX20"
|
||||
#define D_SENSOR_RFSEND "RFSend"
|
||||
#define D_SENSOR_RFRECV "RFrecv"
|
||||
|
||||
// Units
|
||||
#define D_UNIT_AMPERE "安"
|
||||
|
|
|
@ -384,6 +384,8 @@
|
|||
|
||||
#define USE_TX20_WIND_SENSOR // Add support for La Crosse TX20 anemometer (+2k code)
|
||||
|
||||
#define USE_RC_SWITCH // Add support for RF transceiver using library RcSwitch (+2k7 code)
|
||||
|
||||
/*********************************************************************************************\
|
||||
* Debug features are only supported in development branch
|
||||
\*********************************************************************************************/
|
||||
|
|
|
@ -129,6 +129,8 @@ enum UserSelectablePins {
|
|||
GPIO_HX711_SCK, // HX711 Load Cell clock
|
||||
GPIO_HX711_DAT, // HX711 Load Cell data
|
||||
GPIO_TX20_TXD_BLACK, // TX20 Transmission Pin
|
||||
GPIO_RFSEND, // RF transmitter
|
||||
GPIO_RFRECV, // RF receiver
|
||||
GPIO_SENSOR_END };
|
||||
|
||||
// Programmer selectable GPIO functionality offset by user selectable GPIOs
|
||||
|
@ -184,7 +186,8 @@ const char kSensorNames[] PROGMEM =
|
|||
D_SENSOR_PZEM016_RX "|" D_SENSOR_PZEM017_RX "|"
|
||||
D_SENSOR_DFR562 "|" D_SENSOR_SDS0X1_TX "|"
|
||||
D_SENSOR_HX711_SCK "|" D_SENSOR_HX711_DAT "|"
|
||||
D_SENSOR_TX20_TX;
|
||||
D_SENSOR_TX20_TX "|"
|
||||
D_SENSOR_RFSEND "|" D_SENSOR_RFRECV;
|
||||
|
||||
/********************************************************************************************/
|
||||
|
||||
|
@ -341,6 +344,8 @@ const uint8_t kGpioNiceList[GPIO_SENSOR_END] PROGMEM = {
|
|||
GPIO_WS2812, // WS2812 Led string
|
||||
GPIO_IRSEND, // IR remote
|
||||
GPIO_IRRECV, // IR receiver
|
||||
GPIO_RFSEND, // RF transmitter
|
||||
GPIO_RFRECV, // RF receiver
|
||||
GPIO_SR04_TRIG, // SR04 Trigger pin
|
||||
GPIO_SR04_ECHO, // SR04 Echo pin
|
||||
GPIO_TM16CLK, // TM1638 Clock
|
||||
|
|
|
@ -710,6 +710,10 @@ boolean GetUsedInModule(byte val, uint8_t *arr)
|
|||
#ifndef USE_TX20_WIND_SENSOR
|
||||
if (GPIO_TX20_TXD_BLACK == val) { return true; }
|
||||
#endif
|
||||
#ifndef USE_RC_SWITCH
|
||||
if (GPIO_RFSEND == val) { return true; }
|
||||
if (GPIO_RFRECV == val) { return true; }
|
||||
#endif
|
||||
|
||||
|
||||
if ((val >= GPIO_REL1) && (val < GPIO_REL1 + MAX_RELAYS)) {
|
||||
|
@ -1025,6 +1029,10 @@ void GetFeatures()
|
|||
#ifdef USE_TUYA_DIMMER
|
||||
feature_drv2 |= 0x00008000; // xdrv_16_tuyadimmer.ino
|
||||
#endif
|
||||
#ifdef USE_RC_SWITCH
|
||||
feature_drv2 |= 0x00010000; // xdrv_17_rcswitch.ino
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
#ifdef NO_EXTRA_4K_HEAP
|
||||
|
|
|
@ -0,0 +1,184 @@
|
|||
/*
|
||||
xdrv_17_rcswitch.ino - RF transceiver using RcSwitch library for Sonoff-Tasmota
|
||||
|
||||
Copyright (C) 2017 Theo Arends
|
||||
|
||||
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 should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifdef USE_RC_SWITCH
|
||||
/*********************************************************************************************\
|
||||
* RF send and receive using RCSwitch library
|
||||
\*********************************************************************************************/
|
||||
|
||||
#define D_JSON_RF_PROTOCOL "Protocol"
|
||||
#define D_JSON_RF_BITS "Bits"
|
||||
#define D_JSON_RF_DATA "Data"
|
||||
|
||||
#define D_CMND_RFSEND "RFSend"
|
||||
#define D_JSON_RF_PULSE "Pulse"
|
||||
#define D_JSON_RF_REPEAT "Repeat"
|
||||
|
||||
#include <RCSwitch.h>
|
||||
|
||||
RCSwitch mySwitch = RCSwitch();
|
||||
|
||||
#define RF_TIME_AVOID_DUPLICATE 500 // Milliseconds
|
||||
|
||||
unsigned long rf_lasttime = 0;
|
||||
|
||||
void RfReceiveCheck()
|
||||
{
|
||||
if (mySwitch.available()) {
|
||||
|
||||
unsigned long value = mySwitch.getReceivedValue();
|
||||
unsigned int bit_length = mySwitch.getReceivedBitlength();
|
||||
unsigned int delay = mySwitch.getReceivedDelay();
|
||||
unsigned int protocol = mySwitch.getReceivedProtocol();
|
||||
|
||||
snprintf_P(log_data, sizeof(log_data), PSTR("RFR: BitLen %d, Delay %d, Protocol %d, Value %lX (%u)"),
|
||||
bit_length, delay, protocol, value, value);
|
||||
AddLog(LOG_LEVEL_DEBUG);
|
||||
|
||||
unsigned long now = millis();
|
||||
if ((now - rf_lasttime > RF_TIME_AVOID_DUPLICATE) && (value > 0)) {
|
||||
rf_lasttime = now;
|
||||
|
||||
char stemp[16];
|
||||
if (Settings.flag.rf_receive_decimal) {
|
||||
snprintf_P(stemp, sizeof(stemp), PSTR("%u"), (uint32_t)value);
|
||||
} else {
|
||||
snprintf_P(stemp, sizeof(stemp), PSTR("\"%lX\""), (uint32_t)value);
|
||||
}
|
||||
snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("{\"" D_JSON_RFRECEIVED "\":{\"" D_JSON_RF_PROTOCOL "\":%d,\"" D_JSON_RF_BITS "\":%d,\"" D_JSON_RF_DATA "\":%s}}"),
|
||||
protocol, bit_length, stemp);
|
||||
MqttPublishPrefixTopic_P(RESULT_OR_TELE, PSTR(D_JSON_RFRECEIVED));
|
||||
XdrvRulesProcess();
|
||||
#ifdef USE_DOMOTICZ
|
||||
DomoticzSensor(DZ_COUNT, value); // Send value as Domoticz Counter value
|
||||
#endif // USE_DOMOTICZ
|
||||
}
|
||||
mySwitch.resetAvailable();
|
||||
}
|
||||
}
|
||||
|
||||
void RfInit()
|
||||
{
|
||||
if (pin[GPIO_RFSEND] < 99) {
|
||||
mySwitch.enableTransmit(pin[GPIO_RFSEND]);
|
||||
}
|
||||
if (pin[GPIO_RFRECV] < 99) {
|
||||
mySwitch.enableReceive(pin[GPIO_RFRECV]);
|
||||
}
|
||||
}
|
||||
|
||||
/*********************************************************************************************\
|
||||
* Commands
|
||||
\*********************************************************************************************/
|
||||
|
||||
/*
|
||||
* ArduinoJSON entry used to calculate jsonBuf: JSON_OBJECT_SIZE(3) + 40 = 96
|
||||
RFsend:
|
||||
{ "protocol":1, "pulse":320, "repeat":15, "bits":24, "data":551502015 }
|
||||
*/
|
||||
|
||||
boolean RfSendCommand()
|
||||
{
|
||||
boolean serviced = true;
|
||||
|
||||
boolean error = false;
|
||||
char dataBufUc[XdrvMailbox.data_len];
|
||||
|
||||
uint32_t protocol = 0;
|
||||
uint32_t pulse = 0;
|
||||
uint32_t repeat = 0;
|
||||
uint32_t bits = 0;
|
||||
uint32_t data = 0;
|
||||
|
||||
UpperCase(dataBufUc, XdrvMailbox.data);
|
||||
if (!strcasecmp_P(XdrvMailbox.topic, PSTR(D_CMND_RFSEND))) {
|
||||
if (XdrvMailbox.data_len) {
|
||||
StaticJsonBuffer<128> jsonBuf;
|
||||
JsonObject &root = jsonBuf.parseObject(dataBufUc);
|
||||
if (!root.success()) {
|
||||
snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("{\"" D_CMND_RFSEND "\":\"" D_JSON_INVALID_JSON "\"}")); // JSON decode failed
|
||||
}
|
||||
else {
|
||||
snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("{\"" D_CMND_RFSEND "\":\"" D_JSON_DONE "\"}"));
|
||||
|
||||
char parm_uc[10];
|
||||
protocol = root[UpperCase_P(parm_uc, PSTR(D_JSON_RF_PROTOCOL))];
|
||||
pulse = root[UpperCase_P(parm_uc, PSTR(D_JSON_RF_PULSE))];
|
||||
repeat = root[UpperCase_P(parm_uc, PSTR(D_JSON_RF_REPEAT))];
|
||||
bits = root[UpperCase_P(parm_uc, PSTR(D_JSON_RF_BITS))];
|
||||
data = strtoul(root[UpperCase_P(parm_uc, PSTR(D_JSON_RF_DATA))], NULL, 0);
|
||||
|
||||
if (!protocol) { protocol = 1; }
|
||||
mySwitch.setProtocol(protocol);
|
||||
if (!pulse) { pulse = 350; } // Default pulse length for protocol 1
|
||||
mySwitch.setPulseLength(pulse);
|
||||
if (!repeat) { repeat = 10; } // Default at init
|
||||
mySwitch.setRepeatTransmit(repeat);
|
||||
if (!bits) { bits = 24; } // Default 24 bits
|
||||
if (data) {
|
||||
mySwitch.send(data, bits);
|
||||
}
|
||||
else {
|
||||
error = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
error = true;
|
||||
}
|
||||
if (error) {
|
||||
snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("{\"" D_CMND_RFSEND "\":\"" D_JSON_NO " " D_JSON_RF_PROTOCOL ", " D_JSON_RF_PULSE ", " D_JSON_RF_REPEAT ", " D_JSON_RF_BITS " " D_JSON_OR " " D_JSON_RF_DATA "\"}"));
|
||||
}
|
||||
}
|
||||
else serviced = false; // Unknown command
|
||||
|
||||
return serviced;
|
||||
}
|
||||
|
||||
/*********************************************************************************************\
|
||||
* Interface
|
||||
\*********************************************************************************************/
|
||||
|
||||
#define XDRV_17
|
||||
|
||||
boolean Xdrv17(byte function)
|
||||
{
|
||||
boolean result = false;
|
||||
|
||||
if ((pin[GPIO_RFSEND] < 99) || (pin[GPIO_RFRECV] < 99)) {
|
||||
switch (function) {
|
||||
case FUNC_INIT:
|
||||
RfInit();
|
||||
break;
|
||||
case FUNC_EVERY_50_MSECOND:
|
||||
if (pin[GPIO_RFRECV] < 99) {
|
||||
RfReceiveCheck();
|
||||
}
|
||||
break;
|
||||
case FUNC_COMMAND:
|
||||
if (pin[GPIO_RFSEND] < 99) {
|
||||
result = RfSendCommand();
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
#endif // USE_RC_SWITCH
|
|
@ -111,7 +111,7 @@ a_features = [[
|
|||
"USE_KNX_NO_EMULATION","USE_DISPLAY_MODES1TO5","USE_DISPLAY_GRAPH","USE_DISPLAY_LCD",
|
||||
"USE_DISPLAY_SSD1306","USE_DISPLAY_MATRIX","USE_DISPLAY_ILI9341","USE_DISPLAY_EPAPER",
|
||||
"USE_DISPLAY_SH1106","USE_MP3_PLAYER","USE_PCA9685","USE_TUYA_DIMMER",
|
||||
"","","","",
|
||||
"USE_RC_SWITCH","","","",
|
||||
"","","","NO_EXTRA_4K_HEAP",
|
||||
"VTABLES_IN_IRAM","VTABLES_IN_DRAM","VTABLES_IN_FLASH","PIO_FRAMEWORK_ARDUINO_LWIP_HIGHER_BANDWIDTH",
|
||||
"PIO_FRAMEWORK_ARDUINO_LWIP2_LOW_MEMORY","PIO_FRAMEWORK_ARDUINO_LWIP2_HIGHER_BANDWIDTH","DEBUG_THEO","USE_DEBUG_DRIVER"
|
||||
|
|
Loading…
Reference in New Issue