Browse Source

RF/RFBRIDGE Update (#1693)

- remove optional RFRAW_SUPPORT
- enable module when RF_SUPPORT=1, optionally enable RCSwitch
- reorder ifdef checks to treat RFB_DIRECT and old RF_SUPPORT the same
- rename RF_PIN to RFB_RX_PIN
- depend on RF_SUPPORT instead of ITEAD_SONOFF_RFBRIDGE
- runtime TX & RX PIN setting
rules-rpn
Max Prokhorov 5 years ago
committed by GitHub
parent
commit
193cebdbab
No known key found for this signature in database GPG Key ID: 4AEE18F83AFDEB23
26 changed files with 23161 additions and 22981 deletions
  1. +6
    -0
      code/espurna/config/deprecated.h
  2. +27
    -28
      code/espurna/config/general.h
  3. +13
    -17
      code/espurna/config/hardware.h
  4. +1
    -1
      code/espurna/config/progmem.h
  5. +1
    -1
      code/espurna/config/webui.h
  6. BIN
      code/espurna/data/index.all.html.gz
  7. BIN
      code/espurna/data/index.light.html.gz
  8. BIN
      code/espurna/data/index.lightfox.html.gz
  9. BIN
      code/espurna/data/index.rfbridge.html.gz
  10. BIN
      code/espurna/data/index.rfm69.html.gz
  11. BIN
      code/espurna/data/index.sensor.html.gz
  12. BIN
      code/espurna/data/index.small.html.gz
  13. BIN
      code/espurna/data/index.thermostat.html.gz
  14. +1
    -1
      code/espurna/espurna.ino
  15. +258
    -242
      code/espurna/rfbridge.ino
  16. +3228
    -3208
      code/espurna/static/index.all.html.gz.h
  17. +3056
    -3045
      code/espurna/static/index.light.html.gz.h
  18. +2615
    -2604
      code/espurna/static/index.lightfox.html.gz.h
  19. +2667
    -2647
      code/espurna/static/index.rfbridge.html.gz.h
  20. +3709
    -3698
      code/espurna/static/index.rfm69.html.gz.h
  21. +2717
    -2706
      code/espurna/static/index.sensor.html.gz.h
  22. +2615
    -2604
      code/espurna/static/index.small.html.gz.h
  23. +2178
    -2167
      code/espurna/static/index.thermostat.html.gz.h
  24. +1
    -1
      code/espurna/system.ino
  25. +38
    -8
      code/html/custom.js
  26. +30
    -3
      code/html/index.html

+ 6
- 0
code/espurna/config/deprecated.h View File

@ -7,3 +7,9 @@
#warning TELNET_PASSWORD is deprecated! Please replace it with TELNET_AUTHENTICATION
#define TELNET_AUTHENTICATION TELNET_PASSWORD
#endif
// 1.13.6 combines RF_SUPPORT with RFB_DIRECT
#ifdef RF_PIN
#warning RF_PIN is deprecated! Please use RFB_RX_PIN instead
#define RFB_RX_PIN RF_PIN
#endif

+ 27
- 28
code/espurna/config/general.h View File

@ -1223,10 +1223,21 @@
#endif
// -----------------------------------------------------------------------------
// RFBRIDGE
// This module is not compatible with RF_SUPPORT=1
// MQTT RF BRIDGE
// -----------------------------------------------------------------------------
#ifndef RF_SUPPORT
#define RF_SUPPORT 0
#endif
#ifndef RF_DEBOUNCE
#define RF_DEBOUNCE 500
#endif
#ifndef RF_LEARN_TIMEOUT
#define RF_LEARN_TIMEOUT 60000
#endif
#ifndef RF_SEND_TIMES
#define RF_SEND_TIMES 4 // How many times to send the message
#endif
@ -1239,11 +1250,22 @@
#define RF_RECEIVE_DELAY 500 // Interval between recieving in ms (avoid debouncing)
#endif
#ifndef RF_RAW_SUPPORT
#define RF_RAW_SUPPORT 0 // RF raw codes require a specific firmware for the EFM8BB1
// https://github.com/rhx/RF-Bridge-EFM8BB1
// Enable RCSwitch support
// Also possible to use with SONOFF RF BRIDGE, thanks to @wildwiz
// https://github.com/xoseperez/espurna/wiki/Hardware-Itead-Sonoff-RF-Bridge---Direct-Hack
#ifndef RFB_DIRECT
#define RFB_DIRECT 0
#endif
#ifndef RFB_RX_PIN
#define RFB_RX_PIN GPIO_NONE
#endif
#ifndef RFB_TX_PIN
#define RFB_TX_PIN GPIO_NONE
#endif
// -----------------------------------------------------------------------------
// IR Bridge
// -----------------------------------------------------------------------------
@ -1455,29 +1477,6 @@
#define IR_BUTTON_COUNT 0
#endif
//--------------------------------------------------------------------------------
// Custom RF module
// Check http://tinkerman.cat/adding-rf-to-a-non-rf-itead-sonoff/
// Enable support by passing RF_SUPPORT=1 build flag
// This module is not compatible with RFBRIDGE or SONOFF RF
//--------------------------------------------------------------------------------
#ifndef RF_SUPPORT
#define RF_SUPPORT 0
#endif
#ifndef RF_PIN
#define RF_PIN 14
#endif
#ifndef RF_DEBOUNCE
#define RF_DEBOUNCE 500
#endif
#ifndef RF_LEARN_TIMEOUT
#define RF_LEARN_TIMEOUT 60000
#endif
//--------------------------------------------------------------------------------
// Custom RFM69 to MQTT bridge
// Check http://tinkerman.cat/rfm69-wifi-gateway/


+ 13
- 17
code/espurna/config/hardware.h View File

@ -702,19 +702,11 @@
#define LED1_PIN 13
#define LED1_PIN_INVERSE 1
// RFB Direct hack thanks to @wildwiz
// https://github.com/xoseperez/espurna/wiki/Hardware-Itead-Sonoff-RF-Bridge---Direct-Hack
#ifndef RFB_DIRECT
#define RFB_DIRECT 0
#endif
#ifndef RFB_RX_PIN
#define RFB_RX_PIN 4 // GPIO for RX when RFB_DIRECT
#endif
#define RF_SUPPORT 1
#ifndef RFB_TX_PIN
#define RFB_TX_PIN 5 // GPIO for TX when RFB_DIRECT
#endif
// Only used when RFB_DIRECT=1
#define RFB_RX_PIN 4
#define RFB_TX_PIN 5
// When using un-modified harware, ESPurna communicates with the secondary
// MCU EFM8BB1 via UART at 19200 bps so we need to change the speed of
@ -1294,7 +1286,8 @@
// RF
#define RF_SUPPORT 1
#define RF_PIN 4
#define RFB_DIRECT 1
#define RFB_RX_PIN 4
// -----------------------------------------------------------------------------
// HUACANXING H801 & H802
@ -2430,10 +2423,9 @@
#endif
#define DALLAS_PIN 2
#ifndef RF_SUPPORT
#define RF_SUPPORT 1
#endif
#define RF_PIN 14
#define RFB_DIRECT 1
#define RFB_RX_PIN 14
#ifndef DIGITAL_SUPPORT
#define DIGITAL_SUPPORT 1
@ -3674,7 +3666,11 @@
#define NOFUSS_SUPPORT 1
#define UART_MQTT_SUPPORT 1
#define INFLUXDB_SUPPORT 1
#define IR_SUPPORT 1
#define IR_SUPPORT 1
#define RF_SUPPORT 1
#define RFB_DIRECT 1
#define RFB_RX_PIN 4
#elif defined(TRAVIS03)


+ 1
- 1
code/espurna/config/progmem.h View File

@ -97,7 +97,7 @@ PROGMEM const char espurna_modules[] =
#if RFM69_SUPPORT
"RFM69 "
#endif
#if RF_SUPPORT || defined(ITEAD_SONOFF_RFBRIDGE)
#if RF_SUPPORT
"RF "
#endif
#if SCHEDULER_SUPPORT


+ 1
- 1
code/espurna/config/webui.h View File

@ -29,7 +29,7 @@
#endif
#endif
#if defined(ITEAD_SONOFF_RFBRIDGE)
#if RF_SUPPORT == 1
#ifndef WEBUI_IMAGE
#define WEBUI_IMAGE WEBUI_IMAGE_RFBRIDGE
#else


BIN
code/espurna/data/index.all.html.gz View File


BIN
code/espurna/data/index.light.html.gz View File


BIN
code/espurna/data/index.lightfox.html.gz View File


BIN
code/espurna/data/index.rfbridge.html.gz View File


BIN
code/espurna/data/index.rfm69.html.gz View File


BIN
code/espurna/data/index.sensor.html.gz View File


BIN
code/espurna/data/index.small.html.gz View File


BIN
code/espurna/data/index.thermostat.html.gz View File


+ 1
- 1
code/espurna/espurna.ino View File

@ -159,7 +159,7 @@ void setup() {
#if I2C_SUPPORT
i2cSetup();
#endif
#if defined(ITEAD_SONOFF_RFBRIDGE) || RF_SUPPORT
#if RF_SUPPORT
rfbSetup();
#endif
#if ALEXA_SUPPORT


+ 258
- 242
code/espurna/rfbridge.ino View File

@ -1,17 +1,17 @@
/*
RF MODULE
RF BRIDGE MODULE
Copyright (C) 2016-2019 by Xose Pérez <xose dot perez at gmail dot com>
*/
#if defined(ITEAD_SONOFF_RFBRIDGE) || RF_SUPPORT
#if RF_SUPPORT
#include <queue>
#include <Ticker.h>
#if RFB_DIRECT || RF_SUPPORT
#if RFB_DIRECT
#include <RCSwitch.h>
#endif
@ -50,24 +50,25 @@ Copyright (C) 2016-2019 by Xose Pérez <xose dot perez at gmail dot com>
unsigned char _uartbuf[RF_MESSAGE_SIZE+3] = {0};
unsigned char _uartpos = 0;
unsigned char _learnId = 0;
bool _learnStatus = true;
bool _rfbin = false;
#if not RF_SUPPORT
typedef struct {
byte code[RF_MESSAGE_SIZE];
byte times;
} rfb_message_t;
static std::queue<rfb_message_t> _rfb_message_queue;
Ticker _rfb_ticker;
bool _rfb_ticker_active = false;
#endif
#if RFB_DIRECT || RF_SUPPORT
#if RFB_DIRECT
RCSwitch * _rfModem;
bool _learning = false;
#endif
bool _rfb_receive = false;
bool _rfb_transmit = false;
unsigned char _rfb_repeat = RF_SEND_TIMES;
#if WEB_SUPPORT
Ticker _rfb_sendcodes;
#endif
@ -119,9 +120,12 @@ void _rfbWebSocketSendCodes() {
void _rfbWebSocketOnSend(JsonObject& root) {
root["rfbVisible"] = 1;
root["rfbRepeat"] = getSetting("rfbRepeat", RF_SEND_TIMES).toInt();
root["rfbCount"] = relayCount();
#if RF_RAW_SUPPORT
root["rfbrawVisible"] = 1;
#if RFB_DIRECT
root["rfbdirectVisible"] = 1;
root["rfbRX"] = getSetting("rfbRX", RFB_RX_PIN).toInt();
root["rfbTX"] = getSetting("rfbTX", RFB_TX_PIN).toInt();
#endif
_rfb_sendcodes.once_ms(1000, _rfbWebSocketSendCodes);
}
@ -132,41 +136,11 @@ void _rfbWebSocketOnAction(uint32_t client_id, const char * action, JsonObject&
if (strcmp(action, "rfbsend") == 0) rfbStore(data["id"], data["status"], data["data"].as<const char*>());
}
#endif // WEB_SUPPORT
void _rfbAck() {
#if (not RFB_DIRECT) && (not RF_SUPPORT)
DEBUG_MSG_P(PSTR("[RF] Sending ACK\n"));
Serial.println();
Serial.write(RF_CODE_START);
Serial.write(RF_CODE_ACK);
Serial.write(RF_CODE_STOP);
Serial.flush();
Serial.println();
#endif
bool _rfbWebSocketOnReceive(const char * key, JsonVariant& value) {
return (strncmp(key, "rfb", 3) == 0);
}
void _rfbLearn() {
#if RFB_DIRECT || RF_SUPPORT
DEBUG_MSG_P(PSTR("[RF] Entering LEARN mode\n"));
_learning = true;
#else
DEBUG_MSG_P(PSTR("[RF] Sending LEARN\n"));
Serial.println();
Serial.write(RF_CODE_START);
Serial.write(RF_CODE_LEARN);
Serial.write(RF_CODE_STOP);
Serial.flush();
Serial.println();
#endif
#if WEB_SUPPORT
char buffer[100];
snprintf_P(buffer, sizeof(buffer), PSTR("{\"action\": \"rfbLearn\", \"data\":{\"id\": %d, \"status\": %d}}"), _learnId, _learnStatus ? 1 : 0);
wsSend(buffer);
#endif
}
#endif // WEB_SUPPORT
/*
From an hexa char array ("A220EE...") to a byte array (half the size)
@ -183,70 +157,43 @@ static int _rfbToArray(const char * in, byte * out, int length = RF_MESSAGE_SIZE
return n;
}
#if not RF_SUPPORT
void _rfbSendRaw(const byte *message, const unsigned char n = RF_MESSAGE_SIZE) {
for (unsigned char j=0; j<n; j++) {
Serial.write(message[j]);
}
}
void _rfbSend(byte * message) {
#if RFB_DIRECT
unsigned int protocol = message[1];
unsigned int timing =
(message[2] << 8) |
(message[3] << 0) ;
unsigned int bitlength = message[4];
unsigned long rf_code =
(message[5] << 24) |
(message[6] << 16) |
(message[7] << 8) |
(message[8] << 0) ;
_rfModem->setProtocol(protocol);
if (timing > 0) {
_rfModem->setPulseLength(timing);
}
_rfModem->send(rf_code, bitlength);
_rfModem->resetAvailable();
#else
Serial.println();
Serial.write(RF_CODE_START);
Serial.write(RF_CODE_RFOUT);
_rfbSendRaw(message);
Serial.write(RF_CODE_STOP);
Serial.flush();
Serial.println();
#endif
}
void _rfbSend() {
if (!_rfb_transmit) return;
// Check if there is something in the queue
if (_rfb_message_queue.empty()) return;
// Pop the first element
static unsigned long last = 0;
if (millis() - last < RF_SEND_DELAY) return;
last = millis();
// Pop the first message and send it
rfb_message_t message = _rfb_message_queue.front();
_rfb_message_queue.pop();
// Send the message
_rfbSend(message.code);
// If it should be further sent, push it to the stack again
// Push it to the stack again if we need to send it more than once
if (message.times > 1) {
message.times = message.times - 1;
_rfb_message_queue.push(message);
}
// if there are still messages in the queue...
if (_rfb_message_queue.empty()) {
_rfb_ticker.detach();
_rfb_ticker_active = false;
}
yield();
}
void _rfbSend(byte * code, unsigned char times) {
if (!_rfb_transmit) return;
// rc-switch will repeat on its own
#if RFB_DIRECT
times = 1;
#endif
@ -260,18 +207,8 @@ void _rfbSend(byte * code, unsigned char times) {
message.times = times;
_rfb_message_queue.push(message);
// Enable the ticker if not running
if (!_rfb_ticker_active) {
_rfb_ticker_active = true;
_rfb_ticker.attach_ms(RF_SEND_DELAY, _rfbSend);
}
}
#endif // not RF_SUPPORT
#if RF_RAW_SUPPORT
void _rfbSendRawOnce(byte *code, unsigned char length) {
char buffer[length*2];
_rfbToChar(code, buffer, length);
@ -279,8 +216,6 @@ void _rfbSendRawOnce(byte *code, unsigned char length) {
_rfbSendRaw(code, length);
}
#endif // RF_RAW_SUPPORT
bool _rfbMatch(char* code, unsigned char& relayID, unsigned char& value, char* buffer = NULL) {
if (strlen(code) != 18) return false;
@ -386,80 +321,6 @@ void _rfbDecode() {
}
void _rfbReceive() {
#if RFB_DIRECT || RF_SUPPORT
static long learn_start = 0;
if (!_learning && learn_start) {
learn_start = 0;
}
if (_learning) {
if (!learn_start) {
DEBUG_MSG_P(PSTR("[RF] Arming learn timeout\n"));
learn_start = millis();
}
if (learn_start > 0 && millis() - learn_start > RF_LEARN_TIMEOUT) {
DEBUG_MSG_P(PSTR("[RF] Learn timeout triggered\n"));
memset(_uartbuf, 0, sizeof(_uartbuf));
_uartbuf[0] = RF_CODE_LEARN_KO;
_rfbDecode();
_learning = false;
}
}
if (_rfModem->available()) {
static unsigned long last = 0;
if (millis() - last > RF_DEBOUNCE) {
last = millis();
unsigned long rf_code = _rfModem->getReceivedValue();
if ( rf_code > 0) {
DEBUG_MSG_P(PSTR("[RF] Received code: %08X\n"), rf_code);
unsigned int timing = _rfModem->getReceivedDelay();
memset(_uartbuf, 0, sizeof(_uartbuf));
unsigned char *msgbuf = _uartbuf + 1;
_uartbuf[0] = _learning ? RF_CODE_LEARN_OK: RF_CODE_RFIN;
msgbuf[0] = 0xC0;
msgbuf[1] = _rfModem->getReceivedProtocol();
msgbuf[2] = timing >> 8;
msgbuf[3] = timing >> 0;
msgbuf[4] = _rfModem->getReceivedBitlength();
msgbuf[5] = rf_code >> 24;
msgbuf[6] = rf_code >> 16;
msgbuf[7] = rf_code >> 8;
msgbuf[8] = rf_code >> 0;
_rfbDecode();
_learning = false;
}
}
_rfModem->resetAvailable();
}
#else
static bool receiving = false;
while (Serial.available()) {
yield();
byte c = Serial.read();
//DEBUG_MSG_P(PSTR("[RF] Received 0x%02X\n"), c);
if (receiving) {
if (c == RF_CODE_STOP && (_uartpos == 1 || _uartpos == RF_MESSAGE_SIZE + 1)) {
_rfbDecode();
receiving = false;
} else if (_uartpos <= RF_MESSAGE_SIZE) {
_uartbuf[_uartpos++] = c;
} else {
// wrong message, should have received a RF_CODE_STOP
receiving = false;
}
} else if (c == RF_CODE_START) {
_uartpos = 0;
receiving = true;
}
}
#endif
}
bool _rfbCompare(const char * code1, const char * code2) {
return strcmp(&code1[12], &code2[12]) == 0;
}
@ -468,6 +329,14 @@ bool _rfbSameOnOff(unsigned char id) {
return _rfbCompare(rfbRetrieve(id, true).c_str(), rfbRetrieve(id, false).c_str());
}
void _rfbParseRaw(char * raw) {
byte message[RF_MAX_MESSAGE_SIZE];
int len = _rfbToArray(raw, message, 0);
if (len > 0) {
_rfbSendRawOnce(message, len);
}
}
void _rfbParseCode(char * code) {
// The payload may be a code in HEX format ([0-9A-Z]{18}) or
@ -486,28 +355,179 @@ void _rfbParseCode(char * code) {
return;
}
#if RF_RAW_SUPPORT
byte message[RF_MESSAGE_SIZE];
int len = _rfbToArray(tok, message, 0);
if (len) {
tok = strtok(NULL, ",");
byte times = (tok != NULL) ? atoi(tok) : 1;
_rfbSend(message, times);
}
byte message[RF_MAX_MESSAGE_SIZE];
int len = _rfbToArray(tok, message, 0);
if ((len > 0) && (isRFRaw || len != RF_MESSAGE_SIZE)) {
_rfbSendRawOnce(message, len);
} else {
tok = strtok(NULL, ",");
byte times = (tok != NULL) ? atoi(tok) : 1;
_rfbSend(message, times);
}
//
// RF handler implementations
//
#if !RFB_DIRECT // Default for ITEAD SONOFF RFBRIDGE
void _rfbAck() {
DEBUG_MSG_P(PSTR("[RF] Sending ACK\n"));
Serial.println();
Serial.write(RF_CODE_START);
Serial.write(RF_CODE_ACK);
Serial.write(RF_CODE_STOP);
Serial.flush();
Serial.println();
}
void _rfbLearnImpl() {
DEBUG_MSG_P(PSTR("[RF] Sending LEARN\n"));
Serial.println();
Serial.write(RF_CODE_START);
Serial.write(RF_CODE_LEARN);
Serial.write(RF_CODE_STOP);
Serial.flush();
Serial.println();
}
void _rfbSend(byte * message) {
Serial.println();
Serial.write(RF_CODE_START);
Serial.write(RF_CODE_RFOUT);
_rfbSendRaw(message);
Serial.write(RF_CODE_STOP);
Serial.flush();
Serial.println();
}
void _rfbReceive() {
static bool receiving = false;
while (Serial.available()) {
yield();
byte c = Serial.read();
//DEBUG_MSG_P(PSTR("[RF] Received 0x%02X\n"), c);
if (receiving) {
if (c == RF_CODE_STOP && (_uartpos == 1 || _uartpos == RF_MESSAGE_SIZE + 1)) {
_rfbDecode();
receiving = false;
} else if (_uartpos <= RF_MESSAGE_SIZE) {
_uartbuf[_uartpos++] = c;
} else {
// wrong message, should have received a RF_CODE_STOP
receiving = false;
}
} else if (c == RF_CODE_START) {
_uartpos = 0;
receiving = true;
}
#else // RF_RAW_SUPPORT
}
byte message[RF_MESSAGE_SIZE];
if (_rfbToArray(tok, message)) {
tok = strtok(NULL, ",");
byte times = (tok != NULL) ? atoi(tok) : 1;
_rfbSend(message, times);
}
#else // RFB_DIRECT
void _rfbAck() {}
void _rfbLearnImpl() {
DEBUG_MSG_P(PSTR("[RF] Entering LEARN mode\n"));
_learning = true;
}
void _rfbSend(byte * message) {
if (!_rfb_transmit) return;
unsigned int protocol = message[1];
unsigned int timing =
(message[2] << 8) |
(message[3] << 0) ;
unsigned int bitlength = message[4];
unsigned long rf_code =
(message[5] << 24) |
(message[6] << 16) |
(message[7] << 8) |
(message[8] << 0) ;
_rfModem->setProtocol(protocol);
if (timing > 0) {
_rfModem->setPulseLength(timing);
}
_rfModem->send(rf_code, bitlength);
_rfModem->resetAvailable();
}
void _rfbReceive() {
if (!_rfb_receive) return;
static long learn_start = 0;
if (!_learning && learn_start) {
learn_start = 0;
}
if (_learning) {
if (!learn_start) {
DEBUG_MSG_P(PSTR("[RF] Arming learn timeout\n"));
learn_start = millis();
}
if (learn_start > 0 && millis() - learn_start > RF_LEARN_TIMEOUT) {
DEBUG_MSG_P(PSTR("[RF] Learn timeout triggered\n"));
memset(_uartbuf, 0, sizeof(_uartbuf));
_uartbuf[0] = RF_CODE_LEARN_KO;
_rfbDecode();
_learning = false;
}
}
if (_rfModem->available()) {
static unsigned long last = 0;
if (millis() - last > RF_DEBOUNCE) {
last = millis();
unsigned long rf_code = _rfModem->getReceivedValue();
if ( rf_code > 0) {
DEBUG_MSG_P(PSTR("[RF] Received code: %08X\n"), rf_code);
unsigned int timing = _rfModem->getReceivedDelay();
memset(_uartbuf, 0, sizeof(_uartbuf));
unsigned char *msgbuf = _uartbuf + 1;
_uartbuf[0] = _learning ? RF_CODE_LEARN_OK: RF_CODE_RFIN;
msgbuf[0] = 0xC0;
msgbuf[1] = _rfModem->getReceivedProtocol();
msgbuf[2] = timing >> 8;
msgbuf[3] = timing >> 0;
msgbuf[4] = _rfModem->getReceivedBitlength();
msgbuf[5] = rf_code >> 24;
msgbuf[6] = rf_code >> 16;
msgbuf[7] = rf_code >> 8;
msgbuf[8] = rf_code >> 0;
_rfbDecode();
_learning = false;
}
}
_rfModem->resetAvailable();
}
yield();
}
#endif // RFB_DIRECT
void _rfbLearn() {
_rfbLearnImpl();
#if WEB_SUPPORT
char buffer[100];
snprintf_P(buffer, sizeof(buffer), PSTR("{\"action\": \"rfbLearn\", \"data\":{\"id\": %d, \"status\": %d}}"), _learnId, _learnStatus ? 1 : 0);
wsSend(buffer);
#endif
#endif // RF_RAW_SUPPORT
}
#if MQTT_SUPPORT
@ -515,15 +535,19 @@ void _rfbParseCode(char * code) {
void _rfbMqttCallback(unsigned int type, const char * topic, const char * payload) {
if (type == MQTT_CONNECT_EVENT) {
char buffer[strlen(MQTT_TOPIC_RFLEARN) + 3];
snprintf_P(buffer, sizeof(buffer), PSTR("%s/+"), MQTT_TOPIC_RFLEARN);
mqttSubscribe(buffer);
#if not RF_SUPPORT
mqttSubscribe(MQTT_TOPIC_RFOUT);
#endif
#if RF_RAW_SUPPORT
if (_rfb_transmit) {
mqttSubscribe(MQTT_TOPIC_RFOUT);
}
#if !RFB_DIRECT
mqttSubscribe(MQTT_TOPIC_RFRAW);
#endif
}
if (type == MQTT_MESSAGE_EVENT) {
@ -545,21 +569,15 @@ void _rfbMqttCallback(unsigned int type, const char * topic, const char * payloa
}
#if not RF_SUPPORT
bool isRFOut = t.equals(MQTT_TOPIC_RFOUT);
#endif
#if RF_RAW_SUPPORT
bool isRFRaw = !isRFOut && t.equals(MQTT_TOPIC_RFRAW);
#elif not RF_SUPPORT
bool isRFRaw = false;
#endif
if (t.equals(MQTT_TOPIC_RFOUT)) {
_rfbParseCode((char *) payload);
}
#if not RF_SUPPORT
if (isRFOut || isRFRaw) {
_rfbParseCode((char *) payload);
#if !RFB_DIRECT
if (t.equals(MQTT_TOPIC_RFRAW)) {
_rfbParseRaw((char *) payload);
}
#endif // not RF_SUPPORT
#endif
}
@ -571,7 +589,6 @@ void _rfbMqttCallback(unsigned int type, const char * topic, const char * payloa
void _rfbAPISetup() {
#if not RF_SUPPORT
apiRegister(MQTT_TOPIC_RFOUT,
[](char * buffer, size_t len) {
snprintf_P(buffer, len, PSTR("OK"));
@ -580,7 +597,6 @@ void _rfbAPISetup() {
_rfbParseCode((char *) payload);
}
);
#endif // RF_SUPPORT
apiRegister(MQTT_TOPIC_RFLEARN,
[](char * buffer, size_t len) {
@ -603,16 +619,16 @@ void _rfbAPISetup() {
}
);
#if RF_RAW_SUPPORT
#if !RFB_DIRECT
apiRegister(MQTT_TOPIC_RFRAW,
[](char * buffer, size_t len) {
snprintf_P(buffer, len, PSTR("OK"));
},
[](const char * payload) {
_rfbParseCode(payload);
_rfbParseRaw((char *)payload);
}
);
#endif // RF_RAW_SUPPORT
#endif
}
@ -685,8 +701,6 @@ String rfbRetrieve(unsigned char id, bool status) {
return getSetting(key);
}
#if not RF_SUPPORT
void rfbStatus(unsigned char id, bool status) {
String value = rfbRetrieve(id, status);
@ -694,43 +708,29 @@ void rfbStatus(unsigned char id, bool status) {
bool same = _rfbSameOnOff(id);
#if RF_RAW_SUPPORT
byte message[RF_MAX_MESSAGE_SIZE];
int len = _rfbToArray(value.c_str(), message, 0);
byte message[RF_MAX_MESSAGE_SIZE];
int len = _rfbToArray(value.c_str(), message, 0);
if (len == RF_MESSAGE_SIZE && // probably a standard msg
if (len == RF_MESSAGE_SIZE && // probably a standard msg
(message[0] != RF_CODE_START || // raw would start with 0xAA
message[1] != RF_CODE_RFOUT_BUCKET || // followed by 0xB0,
message[2] + 4 != len || // needs a valid length,
message[len-1] != RF_CODE_STOP)) { // and finish with 0x55
if (!_rfbin) {
unsigned char times = same ? 1 : RF_SEND_TIMES;
_rfbSend(message, times);
}
} else {
_rfbSendRawOnce(message, len); // send a raw message
}
#else // RF_RAW_SUPPORT
if (!_rfbin) {
byte message[RF_MESSAGE_SIZE];
_rfbToArray(value.c_str(), message);
unsigned char times = same ? 1 : RF_SEND_TIMES;
unsigned char times = same ? 1 : _rfb_repeat;
_rfbSend(message, times);
}
#endif // RF_RAW_SUPPORT
} else {
_rfbSendRawOnce(message, len); // send a raw message
}
}
_rfbin = false;
}
#endif // not RF_SUPPORT
void rfbLearn(unsigned char id, bool status) {
_learnId = id;
@ -770,33 +770,49 @@ void rfbSetup() {
#if WEB_SUPPORT
wsOnSendRegister(_rfbWebSocketOnSend);
wsOnActionRegister(_rfbWebSocketOnAction);
wsOnReceiveRegister(_rfbWebSocketOnReceive);
#endif
#if TERMINAL_SUPPORT
_rfbInitCommands();
#endif
#if RFB_DIRECT || RF_SUPPORT
_rfb_repeat = getSetting("rfbRepeat", RF_SEND_TIMES).toInt();
#if RFB_DIRECT
unsigned char rx = getSetting("rfbRX", RFB_RX_PIN).toInt();
unsigned char tx = getSetting("rfbTX", RFB_TX_PIN).toInt();
_rfb_receive = gpioValid(rx);
_rfb_transmit = gpioValid(tx);
if (!_rfb_transmit && !_rfb_receive) {
DEBUG_MSG_P(PSTR("[RF] Neither RX or TX are set\n"));
return;
}
_rfModem = new RCSwitch();
#if RF_SUPPORT
_rfModem->enableReceive(RF_PIN);
DEBUG_MSG_P(PSTR("[RF] RF receiver on GPIO %u\n"), RF_PIN);
#else
_rfModem->enableReceive(RFB_RX_PIN);
_rfModem->enableTransmit(RFB_TX_PIN);
_rfModem->setRepeatTransmit(6);
DEBUG_MSG_P(PSTR("[RF] RF receiver on GPIO %u\n"), RFB_RX_PIN);
DEBUG_MSG_P(PSTR("[RF] RF transmitter on GPIO %u\n"), RFB_TX_PIN);
#endif
if (_rfb_receive) {
_rfModem->enableReceive(rx);
DEBUG_MSG_P(PSTR("[RF] RF receiver on GPIO %u\n"), rx);
}
if (_rfb_transmit) {
_rfModem->enableTransmit(tx);
_rfModem->setRepeatTransmit(_rfb_repeat);
DEBUG_MSG_P(PSTR("[RF] RF transmitter on GPIO %u\n"), tx);
}
#else
_rfb_receive = true;
_rfb_transmit = true;
#endif
// Register loop
// Register loop only when properly configured
espurnaRegisterLoop(rfbLoop);
}
void rfbLoop() {
_rfbReceive();
_rfbSend();
}
#endif

+ 3228
- 3208
code/espurna/static/index.all.html.gz.h
File diff suppressed because it is too large
View File


+ 3056
- 3045
code/espurna/static/index.light.html.gz.h
File diff suppressed because it is too large
View File


+ 2615
- 2604
code/espurna/static/index.lightfox.html.gz.h
File diff suppressed because it is too large
View File


+ 2667
- 2647
code/espurna/static/index.rfbridge.html.gz.h
File diff suppressed because it is too large
View File


+ 3709
- 3698
code/espurna/static/index.rfm69.html.gz.h
File diff suppressed because it is too large
View File


+ 2717
- 2706
code/espurna/static/index.sensor.html.gz.h
File diff suppressed because it is too large
View File


+ 2615
- 2604
code/espurna/static/index.small.html.gz.h
File diff suppressed because it is too large
View File


+ 2178
- 2167
code/espurna/static/index.thermostat.html.gz.h
File diff suppressed because it is too large
View File


+ 1
- 1
code/espurna/system.ino View File

@ -159,7 +159,7 @@ void _systemSetupSpecificHardware() {
// These devices use the hardware UART
// to communicate to secondary microcontrollers
#if defined(ITEAD_SONOFF_RFBRIDGE) || (RELAY_PROVIDER == RELAY_PROVIDER_DUAL) || (RELAY_PROVIDER == RELAY_PROVIDER_STM)
#if (RF_SUPPORT && !RFB_DIRECT) || (RELAY_PROVIDER == RELAY_PROVIDER_DUAL) || (RELAY_PROVIDER == RELAY_PROVIDER_STM)
Serial.begin(SERIAL_BAUDRATE);
#endif


+ 38
- 8
code/html/custom.js View File

@ -389,6 +389,40 @@ function doResetThermostatCounters(ask) {
}
<!-- endRemoveIf(!thermostat)-->
function initGPIO(node, name, key, value) {
var template = $("#gpioConfigTemplate").children();
var line = $(template).clone();
$("span.id", line).html(value);
$("select", line).attr("name", key);
line.appendTo(node);
}
function initSelectGPIO(select) {
// TODO: cross-check used GPIOs
// TODO: support 9 & 10 with esp8285 variant
var mapping = [
[153, "NONE"],
[0, "0"],
[1, "1 (U0TXD)"],
[2, "2 (U1TXD)"],
[3, "3 (U0RXD)"],
[4, "4"],
[5, "5"],
[12, "12 (MTDI)"],
[13, "13 (MTCK)"],
[14, "14 (MTMS)"],
[15, "15 (MTDO)"],
];
for (n in mapping) {
var elem = $('<option value="' + mapping[n][0] + '">');
elem.html(mapping[n][1]);
elem.appendTo(select);
}
}
// -----------------------------------------------------------------------------
// Actions
// -----------------------------------------------------------------------------
@ -995,10 +1029,6 @@ function initRelayConfig(data) {
}
// -----------------------------------------------------------------------------
// Sensors & Magnitudes
// -----------------------------------------------------------------------------
function initLeds(data) {
var current = $("#ledConfig > div").length;
@ -1301,10 +1331,6 @@ function processData(data) {
return;
}
if ("rfbrawVisible" === key) {
$("input[name='rfbcode']").attr("maxlength", 116);
}
if ("rfb" === key) {
var rfb = data.rfb;
@ -1865,6 +1891,10 @@ $(function() {
}
<!-- endRemoveIf(!rfm69)-->
$(".gpio-select").each(function(_, elem) {
initSelectGPIO(elem)
});
$(document).on("change", "input", hasChanged);
$(document).on("change", "select", hasChanged);


+ 30
- 3
code/html/index.html View File

@ -1617,13 +1617,40 @@
To learn a new code click <strong>LEARN</strong> (the Sonoff RFBridge will beep) then press a button on the remote, the new code should show up (and the RFBridge will double beep). If the device double beeps but the code does not update it has not been properly learnt. Keep trying.<br /><br />
Modify or create new codes manually and then click <strong>SAVE</strong> to store them in the device memory. If your controlled device uses the same code to switch ON and OFF, learn the code with the ON button and copy paste it to the OFF input box, then click SAVE on the last one to store the value.<br /><br />
Delete any code clicking the <strong>FORGET</strong> button.
<span class="module module-rfbraw"><br /><br />You can also specify 116-chars long RAW codes. Raw codes require a <a rel="noopener" target="_blank" href="https://github.com/rhx/RF-Bridge-EFM8BB1">specific firmware for for the EFM8BB1</a>.</span>
<br /><br />You can also specify any RAW code. For reference see <a rel="noopener" target="_blank" href="https://github.com/Portisch/RF-Bridge-EFM8BB1/wiki/Commands">possible commands for Sonoff RF Bridge EFM8BB1</a> (original firmware supports codes from <strong>0xA0</strong> to <strong>0xA5</strong>).
</h2>
</div>
<div class="page">
<fieldset>
<legend>RF Codes</legend>
<div id="rfbNodes"></div>
<legend>Settings</legend>
<div class="pure-g">
<label class="pure-u-1 pure-u-lg-1-4">Repeats</label>
<div class="pure-u-1 pure-u-lg-1-4"><input class="pure-u-1 pure-u-lg-23-24" name="rfbRepeat" type="number" min="1" tabindex="0" /></div>
<div class="pure-u-0 pure-u-lg-1-2"></div>
<div class="pure-u-0 pure-u-lg-1-4"></div>
<div class="pure-u-1 pure-u-lg-3-4 hint">Number of times to repeat transmission</div>
</div>
<div class="pure-g module module-rfbdirect">
<legend>GPIO</legend>
<div class="pure-u-1 pure-u-lg-1 hint">Pins used by the receiver (RX) and transmitter (TX). Set to <strong>NONE</strong> to disable</div>
<label class="pure-u-1 pure-u-lg-1-4">RX Pin</label>
<select class="pure-u-1 pure-u-lg-1-4 gpio-select" name="rfbRX"></select>
<div class="pure-u-0 pure-u-lg-1-2"></div>
<label class="pure-u-1 pure-u-lg-1-4">TX Pin</label>
<select class="pure-u-1 pure-u-lg-1-4 gpio-select" name="rfbTX"></select>
<div class="pure-u-0 pure-u-lg-1-2"></div>
</div>
</fieldset>
</div>
@ -1693,7 +1720,7 @@
<div class="pure-g">
<div class="pure-u-1 pure-u-lg-1-4"><label>Switch ON</label></div>
<input class="pure-u-1 pure-u-lg-1-3" type="text" maxlength="18" name="rfbcode" data-id="1" data-status="1" />
<input class="pure-u-1 pure-u-lg-1-3" type="text" maxlength="116" name="rfbcode" data-id="1" data-status="1" />
<div class="pure-u-1-3 pure-u-lg-1-8"><button type="button" class="pure-u-23-24 pure-button button-rfb-learn">LEARN</button></div>
<div class="pure-u-1-3 pure-u-lg-1-8"><button type="button" class="pure-u-23-24 pure-button button-rfb-send">SAVE</button></div>
<div class="pure-u-1-3 pure-u-lg-1-8"><button type="button" class="pure-u-23-24 pure-button button-rfb-forget">FORGET</button></div>
@ -1701,7 +1728,7 @@
<div class="pure-g">
<div class="pure-u-1 pure-u-lg-1-4"><label>Switch OFF</label></div>
<input class="pure-u-1 pure-u-lg-1-3" type="text" maxlength="18" name="rfbcode" data-id="1" data-status="0" />
<input class="pure-u-1 pure-u-lg-1-3" type="text" maxlength="116" name="rfbcode" data-id="1" data-status="0" />
<div class="pure-u-1-3 pure-u-lg-1-8"><button type="button" class="pure-u-23-24 pure-button button-rfb-learn">LEARN</button></div>
<div class="pure-u-1-3 pure-u-lg-1-8"><button type="button" class="pure-u-23-24 pure-button button-rfb-send">SAVE</button></div>
<div class="pure-u-1-3 pure-u-lg-1-8"><button type="button" class="pure-u-23-24 pure-button button-rfb-forget">FORGET</button></div>


Loading…
Cancel
Save