From: Dmitry Shalnoff Date: Mon, 6 Jul 2020 19:16:41 +0000 (+0200) Subject: Uploaded from my local repository X-Git-Url: https://git.shalnoff.com/433Utils_NP/commitdiff_plain/be3fd06ed167b773d1833639b0c0bafd24a08e4b?ds=sidebyside Uploaded from my local repository --- be3fd06ed167b773d1833639b0c0bafd24a08e4b diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..7a9421a --- /dev/null +++ b/.gitignore @@ -0,0 +1,22 @@ +# Mac stuff +.DS_Store + +# Compiled Object files +*.slo +*.lo +*.o + +# Compiled Dynamic libraries +*.so +*.dylib + +# Compiled Static libraries +*.lai +*.la +*.a + +# Compiled executables +RPi_utils/RFSniffer +RPi_utils/codesend +RPi_utils/send + diff --git a/.gitmodules b/.gitmodules new file mode 100644 index 0000000..2ddc352 --- /dev/null +++ b/.gitmodules @@ -0,0 +1,3 @@ +[submodule "rc-switch"] + path = rc-switch + url = https://github.com/sui77/rc-switch.git diff --git a/CHANGELOG.md b/CHANGELOG.md new file mode 100644 index 0000000..99e6071 --- /dev/null +++ b/CHANGELOG.md @@ -0,0 +1,19 @@ +# Changelog +All notable changes to this project will be documented in this file. + +The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), +and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). + +## [Unreleased] + +## [0.0.2] - 2020-07-06 +### Added +- CHANGELOG.md +- moved to https://git.shalnoff.com/ + +### Changed +- README.md; Extended with nanoPi building instruction and some notes + + + + diff --git a/LICENSE b/LICENSE new file mode 100644 index 0000000..d48be88 --- /dev/null +++ b/LICENSE @@ -0,0 +1,21 @@ +The MIT License (MIT) + +Copyright (c) 2014-2016 Ninja Blocks Inc. + +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. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. \ No newline at end of file diff --git a/README.md b/README.md new file mode 100644 index 0000000..8859356 --- /dev/null +++ b/README.md @@ -0,0 +1,57 @@ +Hacked from [433Utils](https://github.com/ninjablocks/433Utils) by Dmitry Shalnoff for [Interplay Medium™](https://interplaymedium.org) project. + +# 433Utils, GPIO interrupt-less version + +This s a fork of [433Utils](https://github.com/ninjablocks/433Utils) adapted for NanoPi (and probably other no GPIO interrupt supported devices). This code inherit compatibility with RPi as well. The usage of GPIO interrupt can be switched on and off if required. + +This collection of code designed to assist you in the connection and usage of RF 433MHz transmit and receive modules to/with your device. Despite the name, 433Utils also works with 315MHz transmit and receive modules (tested). + +## Requirements + +1. nanoPi +2. RF 433MHz modules; a transmitter and receiver + +## Building + +### Install dependency if needed + +You have to install WiringNP first (for RPi it is avaliable from oficial repository, so use *apt install ...*) + + git clone https://github.com/friendlyarm/WiringNP + cd WiringNP/ + git checkout nanopi-m1 + chmod 755 build + ./build + +Define macro-variables + noInterrupts in *rc-switch/RCSwitch.cpp* if you woild like to disable interrupt handler. + NANOPI in *xPi_utils/433rx* if you wouls like to use non-interrupt handler (possible on PRi as well, conservatively reduces resource utilization) + +Clone this repo and compile + + cd 433Utils/xPi_utils + make 433rx + +Complex (all utils at once) compilation has not been tested yet. Something might not built or not work properly. Howver you could try: + + make + +## Usage + +### listen + + ./433rx -p -l [Pulse length] + +### send (didn't tested with nanoPi) + sudo ./send systemCode unitCode command + +This command is unaltered from the original rc\_switch distribution. + +### codesend + sudo ./codesend decimalcode + +## Issues + +Due to limitiations in the implementation of interrupt-driven routines in the underlying RCSwitch library, it is currently not possible to use both the send and receive functionality within the one program. + + diff --git a/rc-switch/.gitignore b/rc-switch/.gitignore new file mode 100644 index 0000000..d0972bb --- /dev/null +++ b/rc-switch/.gitignore @@ -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 + diff --git a/rc-switch/.travis.yml b/rc-switch/.travis.yml new file mode 100644 index 0000000..4ac2b7d --- /dev/null +++ b/rc-switch/.travis.yml @@ -0,0 +1,26 @@ +language: python +python: + - "2.7" + +# Cache PlatformIO packages using Travis CI container-based infrastructure +sudo: false +cache: + directories: + - "~/.platformio" + +env: + - PLATFORMIO_CI_SRC=examples/Webserver/ + - PLATFORMIO_CI_SRC=examples/ReceiveDemo_Simple/ + - PLATFORMIO_CI_SRC=examples/TypeC_Intertechno/ + - PLATFORMIO_CI_SRC=examples/TypeD_REV/ + - PLATFORMIO_CI_SRC=examples/TypeA_WithDIPSwitches/ + - PLATFORMIO_CI_SRC=examples/TypeA_WithDIPSwitches_Lightweight/ + - PLATFORMIO_CI_SRC=examples/TypeB_WithRotaryOrSlidingSwitches/ + - PLATFORMIO_CI_SRC=examples/SendDemo/ + - PLATFORMIO_CI_SRC=examples/ReceiveDemo_Advanced/ + +install: + - pip install -U platformio + +script: + - platformio ci --lib="." --board=diecimilaatmega328 diff --git a/rc-switch/Makefile_ b/rc-switch/Makefile_ new file mode 100644 index 0000000..28fe0f3 --- /dev/null +++ b/rc-switch/Makefile_ @@ -0,0 +1,7 @@ +all: send + +send: RCSwitch.o send.o + $(CXX) $(CXXFLAGS) $(LDFLAGS) $+ -o $@ -lwiringPi + +clean: + $(RM) *.o send diff --git a/rc-switch/RCSwitch.cpp b/rc-switch/RCSwitch.cpp new file mode 100644 index 0000000..1c36970 --- /dev/null +++ b/rc-switch/RCSwitch.cpp @@ -0,0 +1,691 @@ +/* + 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 / .(at)gmail(dot)com + - Andreas Steinel / A.(at)gmail(dot)com + - Max Horn / max(at)quendi(dot)de + - Robert ter Vehn / .(at)gmail(dot)com + - Johann Richard / .(at)gmail(dot)com + - Vlad Gheorghe / .(at)gmail(dot)com https://github.com/vgheo + - Dmitry Shalnov / (at)interplaymedium(dot)org + + 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 +*/ + +#define noInterrupts + +#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 + +#ifdef ESP8266 + // 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. + */ +#ifdef ESP8266 +static const RCSwitch::Protocol proto[] = { +#else +static const RCSwitch::Protocol PROGMEM proto[] = { +#endif + { 350, { 1, 31 }, { 1, 3 }, { 3, 1 } }, // protocol 1 + { 650, { 1, 10 }, { 1, 2 }, { 2, 1 } }, // protocol 2 + { 100, { 30, 71 }, { 4, 11 }, { 9, 6 } }, // protocol 3 + { 380, { 1, 6 }, { 1, 3 }, { 3, 1 } }, // protocol 4 + { 500, { 6, 14 }, { 1, 2 }, { 2, 1 } }, // protocol 5 +}; + +enum { + numProto = sizeof(proto) / sizeof(proto[0]) +}; + +#if not defined( RCSwitchDisableReceiving ) +unsigned long RCSwitch::nReceivedValue = 0; +unsigned int RCSwitch::nReceivedBitlength = 0; +unsigned int RCSwitch::nReceivedDelay = 0; +unsigned int RCSwitch::nReceivedProtocol = 0; +int RCSwitch::nReceiveTolerance = 60; +const unsigned int RCSwitch::nSeparationLimit = 4600; +// 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" ??? + } +#ifdef ESP8266 + 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); + } + +#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) { + digitalWrite(this->nTransmitterPin, HIGH); + delayMicroseconds( this->protocol.pulseLength * pulses.high); + digitalWrite(this->nTransmitterPin, LOW); + 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; +#ifndef noInterrupts + #if defined(RaspberryPi) // Raspberry Pi + wiringPiISR(this->nReceiverInterrupt, INT_EDGE_BOTH, &handleInterrupt); + #else // Arduino + attachInterrupt(this->nReceiverInterrupt, handleInterrupt, CHANGE); + #endif +#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) { +#ifdef ESP8266 + const Protocol &pro = proto[p-1]; +#else + Protocol pro; + memcpy_P(&pro, &proto[p-1], sizeof(Protocol)); +#endif + + unsigned long code = 0; + const unsigned int delay = RCSwitch::timings[0] / pro.syncFactor.low; + const unsigned int delayTolerance = delay * RCSwitch::nReceiveTolerance / 100; + + for (unsigned int i = 1; 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; +} + +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; +} + +// where no wiringPiISR supported (nanopi) + +void RCSwitch::handleNoInterrupt( unsigned char PIN ){ + + static unsigned char dr, drPrev; + + dr = digitalRead( PIN ); + + if (dr != drPrev) { + handleInterrupt(); + drPrev = dr; + } +} + +#endif diff --git a/rc-switch/RCSwitch.h b/rc-switch/RCSwitch.h new file mode 100644 index 0000000..a2abb9f --- /dev/null +++ b/rc-switch/RCSwitch.h @@ -0,0 +1,156 @@ +/* + 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 / .(at)gmail(dot)com + - Max Horn / max(at)quendi(dot)de + - Robert ter Vehn / .(at)gmail(dot)com + - Dmitry Shalnov / (at)interplaymedium(dot)org + + 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 /* memcpy */ + #include /* abs */ + #include +#else + #include "WProgram.h" +#endif + +#include + + +// 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 + + struct HighLow { + uint8_t high; + uint8_t low; + }; + + struct Protocol { + int pulseLength; + HighLow syncFactor; + HighLow zero; + HighLow one; + }; + + void setProtocol(Protocol protocol); + void setProtocol(int nProtocol); + void setProtocol(int nProtocol, int nPulseLength); + + static void handleNoInterrupt( unsigned char PIN ); + + 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; + static unsigned long nReceivedValue; + static unsigned int nReceivedBitlength; + static unsigned int nReceivedDelay; + 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 diff --git a/rc-switch/README.md b/rc-switch/README.md new file mode 100644 index 0000000..b09fcee --- /dev/null +++ b/rc-switch/README.md @@ -0,0 +1,41 @@ +This is modified version hacked from [433Utils](https://github.com/ninjablocks/433Utils) by Dmitry Shalnoff for [Interplay Medium™](https://interplaymedium.org) project. +This fork adapted for NanoPi (and probably other no GPIO interrupt supported devices). This code inherit compatibility with RPi as well. + +# 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 + +## 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 + +### 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. diff --git a/rc-switch/examples/ReceiveDemo_Advanced/ReceiveDemo_Advanced.pde b/rc-switch/examples/ReceiveDemo_Advanced/ReceiveDemo_Advanced.pde new file mode 100644 index 0000000..18380d3 --- /dev/null +++ b/rc-switch/examples/ReceiveDemo_Advanced/ReceiveDemo_Advanced.pde @@ -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 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(); + } +} diff --git a/rc-switch/examples/ReceiveDemo_Advanced/helperfunctions.ino b/rc-switch/examples/ReceiveDemo_Advanced/helperfunctions.ino new file mode 100644 index 0000000..669813d --- /dev/null +++ b/rc-switch/examples/ReceiveDemo_Advanced/helperfunctions.ino @@ -0,0 +1,20 @@ +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; +} diff --git a/rc-switch/examples/ReceiveDemo_Advanced/output.ino b/rc-switch/examples/ReceiveDemo_Advanced/output.ino new file mode 100644 index 0000000..ebd53d4 --- /dev/null +++ b/rc-switch/examples/ReceiveDemo_Advanced/output.ino @@ -0,0 +1,52 @@ +void output(unsigned long decimal, unsigned int length, unsigned int delay, unsigned int* raw, unsigned int protocol) { + + if (decimal == 0) { + Serial.print("Unknown encoding."); + } else { + 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(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; +} + diff --git a/rc-switch/examples/ReceiveDemo_Simple/ReceiveDemo_Simple.pde b/rc-switch/examples/ReceiveDemo_Simple/ReceiveDemo_Simple.pde new file mode 100644 index 0000000..ed1d180 --- /dev/null +++ b/rc-switch/examples/ReceiveDemo_Simple/ReceiveDemo_Simple.pde @@ -0,0 +1,35 @@ +/* + Simple example for receiving + + https://github.com/sui77/rc-switch/ +*/ + +#include + +RCSwitch mySwitch = RCSwitch(); + +void setup() { + Serial.begin(9600); + mySwitch.enableReceive(0); // Receiver on interrupt 0 => that is pin #2 +} + +void loop() { + if (mySwitch.available()) { + + int value = mySwitch.getReceivedValue(); + + if (value == 0) { + Serial.print("Unknown encoding"); + } else { + 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(); + } +} diff --git a/rc-switch/examples/SendDemo/SendDemo.pde b/rc-switch/examples/SendDemo/SendDemo.pde new file mode 100644 index 0000000..d1e1cd2 --- /dev/null +++ b/rc-switch/examples/SendDemo/SendDemo.pde @@ -0,0 +1,57 @@ +/* + Example for different sending methods + + https://github.com/sui77/rc-switch/ + +*/ + +#include + +RCSwitch mySwitch = RCSwitch(); + +void setup() { + + Serial.begin(9600); + + // Transmitter is connected to Arduino Pin #10 + mySwitch.enableTransmit(10); + + // Optional set pulse length. + // mySwitch.setPulseLength(320); + + // Optional set protocol (default is 1, will work for most outlets) + // mySwitch.setProtocol(2); + + // Optional set number of transmission repetitions. + // mySwitch.setRepeatTransmit(15); + +} + +void loop() { + + /* See Example: TypeA_WithDIPSwitches */ + mySwitch.switchOn("11111", "00010"); + delay(1000); + mySwitch.switchOn("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); +} diff --git a/rc-switch/examples/TypeA_WithDIPSwitches/TypeA_WithDIPSwitches.pde b/rc-switch/examples/TypeA_WithDIPSwitches/TypeA_WithDIPSwitches.pde new file mode 100644 index 0000000..14f7d2a --- /dev/null +++ b/rc-switch/examples/TypeA_WithDIPSwitches/TypeA_WithDIPSwitches.pde @@ -0,0 +1,40 @@ +/* + Example for outlets which are configured with a 10 pole DIP switch. + + https://github.com/sui77/rc-switch/ +*/ + +#include + +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); + +} diff --git a/rc-switch/examples/TypeA_WithDIPSwitches_Lightweight/TypeA_WithDIPSwitches_Lightweight.ino b/rc-switch/examples/TypeA_WithDIPSwitches_Lightweight/TypeA_WithDIPSwitches_Lightweight.ino new file mode 100644 index 0000000..214daf4 --- /dev/null +++ b/rc-switch/examples/TypeA_WithDIPSwitches_Lightweight/TypeA_WithDIPSwitches_Lightweight.ino @@ -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); +} + diff --git a/rc-switch/examples/TypeB_WithRotaryOrSlidingSwitches/TypeB_WithRotaryOrSlidingSwitches.pde b/rc-switch/examples/TypeB_WithRotaryOrSlidingSwitches/TypeB_WithRotaryOrSlidingSwitches.pde new file mode 100644 index 0000000..e8568e2 --- /dev/null +++ b/rc-switch/examples/TypeB_WithRotaryOrSlidingSwitches/TypeB_WithRotaryOrSlidingSwitches.pde @@ -0,0 +1,40 @@ +/* + Example for outlets which are configured with two rotary/sliding switches. + + https://github.com/sui77/rc-switch/ +*/ + +#include + +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); + +} diff --git a/rc-switch/examples/TypeC_Intertechno/TypeC_Intertechno.pde b/rc-switch/examples/TypeC_Intertechno/TypeC_Intertechno.pde new file mode 100644 index 0000000..0fc69c7 --- /dev/null +++ b/rc-switch/examples/TypeC_Intertechno/TypeC_Intertechno.pde @@ -0,0 +1,40 @@ +/* + Example for Intertechno outlets + + https://github.com/sui77/rc-switch/ +*/ + +#include + +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); + +} \ No newline at end of file diff --git a/rc-switch/examples/TypeD_REV/TypeD_REV.ino b/rc-switch/examples/TypeD_REV/TypeD_REV.ino new file mode 100644 index 0000000..8782729 --- /dev/null +++ b/rc-switch/examples/TypeD_REV/TypeD_REV.ino @@ -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 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); + +} diff --git a/rc-switch/examples/Webserver/Webserver.pde b/rc-switch/examples/Webserver/Webserver.pde new file mode 100644 index 0000000..66668e7 --- /dev/null +++ b/rc-switch/examples/Webserver/Webserver.pde @@ -0,0 +1,154 @@ +/* + A simple RCSwitch/Ethernet/Webserver demo + + https://github.com/sui77/rc-switch/ +*/ + +#include +#include +#include + +// 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(""); + c.println(""); + c.println( "RCSwitch Webserver Demo"); + c.println( ""); + c.println(""); + c.println(""); + c.println( "

RCSwitch Webserver Demo

"); + c.println( ""); + c.println( ""); + c.println( "
"); + c.println( "https://github.com/sui77/rc-switch/"); + c.println(""); + c.println(""); +} + +/** + * 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'; +} \ No newline at end of file diff --git a/rc-switch/keywords.txt b/rc-switch/keywords.txt new file mode 100644 index 0000000..2474367 --- /dev/null +++ b/rc-switch/keywords.txt @@ -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) +####################################### diff --git a/xPi_utils/433rx.cpp b/xPi_utils/433rx.cpp new file mode 100644 index 0000000..0c7fb6f --- /dev/null +++ b/xPi_utils/433rx.cpp @@ -0,0 +1,109 @@ +/* + 433mHz module reader + + Created by Dmitry Shalnov (c) 2019 for Interplay Medium™ project. + + Based on RFSniffer.cpp http://code.google.com/p/rc-switch/ by @justy + License: MIT +*/ + +#include "../rc-switch/RCSwitch.h" +#include +#include +#include + +RCSwitch mySwitch; + +void usage(void) +{ + printf("433mHz module reader. Created by Dmitry Shalnoff [interplaymedium.org] © 2019, Ver 0.0.2.\n"); + printf("Usage:\n"); + printf(" -l pulse length (optional)\n"); + printf(" -p GPIO pin\n"); + exit (8); +} + + +int main(int argc, char *argv[]) { + + int pulseLength = 0; + int PIN = 0; // default + + // commandline parser + + int argCnt = argc; + + if ( argCnt > 2 && argv[1][0] == '-' && argv[ argCnt - 1 ][0] != '-' ){ + + argCnt--; + + while (argCnt > 0) { + + if ( argv[ argCnt ][0] == '-' && argv[ argCnt + 1 ][0] != '-' ) { + + switch (argv[ argCnt ][1]) + { + case 'l': + pulseLength = atoi( argv[ argCnt + 1 ] ); + printf("Pulse length: %d\n",pulseLength); + break; + + case 'p': + PIN = atoi( argv[ argCnt + 1 ] ); + printf("GPIO: %d\n", PIN);; + break; + + default: + printf("Wrong Argument: %s\n", argv[ argCnt ]); + usage(); + } + } + + argCnt--; + } + } else { + usage(); + } + + // --------------------- + + if(wiringPiSetup() == -1) { + printf("wiringPiSetup failed, exiting..."); + return 0; + } + + pinMode (PIN, INPUT); + mySwitch = RCSwitch(); + if (pulseLength != 0) mySwitch.setPulseLength(pulseLength); + mySwitch.enableReceive( PIN ); + + while(1) { + +#ifdef NANOPI + mySwitch.handleNoInterrupt( PIN ); // polling handler, nanoPi WiringNP (no interrupts supported) +#endif + + if (mySwitch.available()) { + + int value = mySwitch.getReceivedValue(); + + if (value == 0) { + printf("Unknown encoding\n"); + } else { + printf("Received %i\n", mySwitch.getReceivedValue() ); + } + + fflush(stdout); + mySwitch.resetAvailable(); + } +#ifndef NANOPI + usleep(100); +#endif + + } + + exit(0); + + +} + diff --git a/xPi_utils/Makefile b/xPi_utils/Makefile new file mode 100644 index 0000000..cb5acdd --- /dev/null +++ b/xPi_utils/Makefile @@ -0,0 +1,21 @@ + +# Defines the RPI variable which is needed by rc-switch/RCSwitch.h +CXXFLAGS=-DRPI + +all: send codesend RFSniffer + +send: ../rc-switch/RCSwitch.o send.o + $(CXX) $(CXXFLAGS) $(LDFLAGS) $+ -o $@ -lwiringPi -lwiringPiDev -lcrypt + +codesend: ../rc-switch/RCSwitch.o codesend.o + $(CXX) $(CXXFLAGS) $(LDFLAGS) $+ -o $@ -lwiringPi -lwiringPiDev -lcrypt + +RFSniffer: ../rc-switch/RCSwitch.o RFSniffer.o + $(CXX) $(CXXFLAGS) $(LDFLAGS) $+ -o $@ -lwiringPi -lwiringPiDev -lcrypt + +433rx: ../rc-switch/RCSwitch.o 433rx.o + $(CXX) $(CXXFLAGS) $(LDFLAGS) $+ -o $@ -lwiringPi -lwiringPiDev -lcrypt + +clean: + $(RM) ../rc-switch/*.o *.o send codesend servo RFSniffer + diff --git a/xPi_utils/RFSniffer.cpp b/xPi_utils/RFSniffer.cpp new file mode 100644 index 0000000..8920cf9 --- /dev/null +++ b/xPi_utils/RFSniffer.cpp @@ -0,0 +1,65 @@ +/* + RFSniffer + + Usage: ./RFSniffer [] + [] = optional + + Hacked from http://code.google.com/p/rc-switch/ + by @justy to provide a handy RF code sniffer +*/ + +#include "../rc-switch/RCSwitch.h" +#include +#include +#include + + +RCSwitch mySwitch; + + + +int main(int argc, char *argv[]) { + + // This pin is not the first pin on the RPi GPIO header! + // Consult https://projects.drogon.net/raspberry-pi/wiringpi/pins/ + // for more information. + int PIN = 0; // 2 + + if(wiringPiSetup() == -1) { + printf("wiringPiSetup failed, exiting..."); + return 0; + } + + int pulseLength = 0; + if (argv[1] != NULL) pulseLength = atoi(argv[1]); + + mySwitch = RCSwitch(); + if (pulseLength != 0) mySwitch.setPulseLength(pulseLength); + mySwitch.enableReceive(PIN); // Receiver on interrupt 0 => that is pin #2 + + + while(1) { + + if (mySwitch.available()) { + + int value = mySwitch.getReceivedValue(); + + if (value == 0) { + printf("Unknown encoding\n"); + } else { + + printf("Received %i\n", mySwitch.getReceivedValue() ); + } + + fflush(stdout); + mySwitch.resetAvailable(); + } + usleep(100); + + } + + exit(0); + + +} + diff --git a/xPi_utils/codesend.cpp b/xPi_utils/codesend.cpp new file mode 100644 index 0000000..afed6fc --- /dev/null +++ b/xPi_utils/codesend.cpp @@ -0,0 +1,58 @@ +/* +Usage: ./codesend decimalcode [protocol] [pulselength] +decimalcode - As decoded by RFSniffer +protocol - According to rc-switch definitions +pulselength - pulselength in microseconds + + 'codesend' hacked from 'send' by @justy + + - The provided rc_switch 'send' command uses the form systemCode, unitCode, command + which is not suitable for our purposes. Instead, we call + send(code, length); // where length is always 24 and code is simply the code + we find using the RF_sniffer.ino Arduino sketch. + +(Use RF_Sniffer.ino to check that RF signals are being produced by the RPi's transmitter +or your remote control) +*/ +#include "../rc-switch/RCSwitch.h" +#include +#include + + +int main(int argc, char *argv[]) { + + // This pin is not the first pin on the RPi GPIO header! + // Consult https://projects.drogon.net/raspberry-pi/wiringpi/pins/ + // for more information. + int PIN = 0; + + // Parse the first parameter to this command as an integer + int protocol = 0; // A value of 0 will use rc-switch's default value + int pulseLength = 0; + + // If no command line argument is given, print the help text + if (argc == 1) { + printf("Usage: %s decimalcode [protocol] [pulselength]\n", argv[0]); + printf("decimalcode\t- As decoded by RFSniffer\n"); + printf("protocol\t- According to rc-switch definitions\n"); + printf("pulselength\t- pulselength in microseconds\n"); + return -1; + } + + // Change protocol and pulse length accroding to parameters + int code = atoi(argv[1]); + if (argc >= 3) protocol = atoi(argv[2]); + if (argc >= 4) pulseLength = atoi(argv[3]); + + if (wiringPiSetup () == -1) return 1; + printf("sending code[%i]\n", code); + RCSwitch mySwitch = RCSwitch(); + if (protocol != 0) mySwitch.setProtocol(protocol); + if (pulseLength != 0) mySwitch.setPulseLength(pulseLength); + mySwitch.enableTransmit(PIN); + + mySwitch.send(code, 24); + + return 0; + +} diff --git a/xPi_utils/send.cpp b/xPi_utils/send.cpp new file mode 100644 index 0000000..575f27e --- /dev/null +++ b/xPi_utils/send.cpp @@ -0,0 +1,60 @@ +/* + Usage: ./send + Command is 0 for OFF and 1 for ON + */ + +#include "../rc-switch/RCSwitch.h" +#include +#include + +int main(int argc, char *argv[]) { + + /* + output PIN is hardcoded for testing purposes + see https://projects.drogon.net/raspberry-pi/wiringpi/pins/ + for pin mapping of the raspberry pi GPIO connector + */ + int PIN = 0; + const char* code[6] = { "00000", "10000", "01000", "00100", "00010", "00001" }; + + if (argc < 4) { + printf("Sending 433 MHz remote plug control codes, hardcoded on wiringpi pin %d.\n", PIN); + printf("Usage: %s [pulseLength]\n", argv[0]); + printf("systemCode - First five settings of Type A 10 pole DIP switch, e.g. 11111\n"); + printf("unitCode - Switch number [1 .. 5] or [10000 .. 00001]\n"); + printf("command - 0 for OFF and 1 for ON\n"); + printf("pulseLength - optional pulse length\n"); + return -1; + } + + char* systemCode = argv[1]; + const char* unitCode; + if (strlen(argv[2]) == 5) { + unitCode = argv[2]; + } else if (atoi(argv[2]) > 0 and atoi(argv[2]) < 6) { + unitCode = code[atoi(argv[2])]; + } else { + return -1; + } + int command = atoi(argv[3]); + + if (wiringPiSetup () == -1) return 1; + printf("sending systemCode[%s] unitCode[%s] command[%i]\n", systemCode, unitCode, command); + RCSwitch mySwitch = RCSwitch(); + if (argv[4] != NULL) + mySwitch.setPulseLength(atoi(argv[4])); + mySwitch.enableTransmit(PIN); + + switch(command) { + case 1: + mySwitch.switchOn(systemCode, unitCode); + break; + case 0: + mySwitch.switchOff(systemCode, unitCode); + break; + default: + printf("command[%i] is unsupported\n", command); + return -1; + } + return 0; +}