Browse Source

Merge branch 'dev' into light

Conflicts:
	code/espurna/config/general.h
	code/espurna/config/hardware.h
	code/espurna/hardware.ino
	code/html/custom.css
	code/html/custom.js
fastled
Xose Pérez 7 years ago
parent
commit
3c21dc3e78
14 changed files with 578 additions and 23 deletions
  1. +1
    -0
      code/espurna/config/arduino.h
  2. +1
    -1
      code/espurna/config/debug.h
  3. +14
    -2
      code/espurna/config/general.h
  4. +25
    -0
      code/espurna/config/hardware.h
  5. +12
    -3
      code/espurna/espurna.ino
  6. +8
    -0
      code/espurna/hardware.ino
  7. +2
    -3
      code/espurna/mqtt.ino
  8. +26
    -9
      code/espurna/relay.ino
  9. +307
    -0
      code/espurna/rfbridge.ino
  10. +31
    -2
      code/espurna/web.ino
  11. +21
    -3
      code/html/custom.css
  12. +60
    -0
      code/html/custom.js
  13. +49
    -0
      code/html/index.html
  14. +21
    -0
      code/platformio.ini

+ 1
- 0
code/espurna/config/arduino.h View File

@ -30,6 +30,7 @@
//#define LED_CONTROLLER
//#define H801_LED_CONTROLLER
//#define ESPURNA_H
//#define SONOFF_RFBRIDGE
//--------------------------------------------------------------------------------
// Features (values below are non-default values)


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

@ -1,6 +1,6 @@
#define DEBUG_MESSAGE_MAX_LENGTH 80
#ifdef SONOFF_DUAL
#if defined(SONOFF_DUAL)
#undef DEBUG_PORT
#endif


+ 14
- 2
code/espurna/config/general.h View File

@ -23,8 +23,8 @@
// To receive the message son the destination computer use nc:
// nc -ul 8111
#define DEBUG_UDP_IP IPAddress(192, 168, 1, 100)
#define DEBUG_UDP_PORT 8113
//#define DEBUG_UDP_IP IPAddress(192, 168, 1, 100)
//#define DEBUG_UDP_PORT 8113
//--------------------------------------------------------------------------------
// EEPROM
@ -136,6 +136,7 @@ PROGMEM const char* const custom_reset_string[] = {
#define RELAY_PROVIDER_RELAY 0
#define RELAY_PROVIDER_DUAL 1
#define RELAY_PROVIDER_LIGHT 2
#define RELAY_PROVIDER_RFBRIDGE 3
// Pulse time in milliseconds
#define RELAY_PULSE_TIME 1.0
@ -250,6 +251,9 @@ PROGMEM const char* const custom_reset_string[] = {
#define MQTT_TOPIC_HOSTNAME "host"
#define MQTT_TOPIC_TIME "time"
#define MQTT_TOPIC_ANALOG "analog"
#define MQTT_TOPIC_RFOUT "rfout"
#define MQTT_TOPIC_RFIN "rfin"
#define MQTT_TOPIC_RFLEARN "rflearn"
// Lights
#define MQTT_TOPIC_CHANNEL "channel"
@ -351,3 +355,11 @@ PROGMEM const char* const custom_reset_string[] = {
// this device should be discoberable and respond to Alexa commands.
// Both ENABLE_FAUXMO and fauxmoEnabled should be 1 for Alexa support to work.
#define FAUXMO_ENABLED 1
// -----------------------------------------------------------------------------
// RFBRIDGE
// -----------------------------------------------------------------------------
#define RF_SEND_TIMES 4 // How many times to send the message
#define RF_SEND_DELAY 250 // Interval between sendings in ms

+ 25
- 0
code/espurna/config/hardware.h View File

@ -161,6 +161,7 @@
#define SERIAL_BAUDRATE 19230
#undef RELAY_PROVIDER
#define RELAY_PROVIDER RELAY_PROVIDER_DUAL
#define DUMMY_RELAY_COUNT 2
#elif defined(SONOFF_4CH)
@ -230,9 +231,25 @@
#define LED1_PIN_INVERSE 1
#define RELAY_PROVIDER RELAY_PROVIDER_LIGHT
#define LIGHT_PROVIDER LIGHT_PROVIDER_DIMMER
#define DUMMY_RELAY_COUNT 1
#define LIGHT_CH1_PIN 12
#define LIGHT_CH1_INVERSE 0
#elif defined(SONOFF_RFBRIDGE)
#define MANUFACTURER "ITEAD"
#define DEVICE "RFBRIDGE"
#define BUTTON1_PIN 0
#define BUTTON1_MODE BUTTON_PUSHBUTTON | BUTTON_DEFAULT_HIGH
#define LED1_PIN 13
#define LED1_PIN_INVERSE 1
#undef SERIAL_BAUDRATE
#define SERIAL_BAUDRATE 19200
#undef RELAY_PROVIDER
#define RELAY_PROVIDER RELAY_PROVIDER_RFBRIDGE
#define DUMMY_RELAY_COUNT 6
#define TRACK_RELAY_STATUS 0
// -----------------------------------------------------------------------------
// Electrodragon boards
// -----------------------------------------------------------------------------
@ -280,6 +297,7 @@
#define DEVICE "AI_LIGHT"
#define RELAY_PROVIDER RELAY_PROVIDER_LIGHT
#define LIGHT_PROVIDER LIGHT_PROVIDER_MY9192
#define DUMMY_RELAY_COUNT 1
#define MY9291_DI_PIN 13
#define MY9291_DCKI_PIN 15
@ -297,6 +315,7 @@
#define LED1_PIN_INVERSE 1
#define RELAY_PROVIDER RELAY_PROVIDER_LIGHT
#define LIGHT_PROVIDER LIGHT_PROVIDER_DIMMER
#define DUMMY_RELAY_COUNT 1
#define LIGHT_CH1_PIN 14 // RED
#define LIGHT_CH2_PIN 5 // GREEN
@ -320,6 +339,7 @@
#define LED1_PIN_INVERSE 1
#define RELAY_PROVIDER RELAY_PROVIDER_LIGHT
#define LIGHT_PROVIDER LIGHT_PROVIDER_DIMMER
#define DUMMY_RELAY_COUNT 1
#define LIGHT_CH1_PIN 15 // RED
#define LIGHT_CH2_PIN 13 // GREEN
@ -540,6 +560,11 @@
#define BUTTON_SET_PULLUP 4
#endif
// Does the board track the relay status?
#ifndef TRACK_RELAY_STATUS
#define TRACK_RELAY_STATUS 1
#endif
// Relay providers
#ifndef RELAY_PROVIDER
#define RELAY_PROVIDER RELAY_PROVIDER_RELAY


+ 12
- 3
code/espurna/espurna.ino View File

@ -118,19 +118,22 @@ unsigned char customReset() {
}
void hardwareSetup() {
EEPROM.begin(4096);
#ifdef DEBUG_PORT
DEBUG_PORT.begin(SERIAL_BAUDRATE);
if (customReset() == CUSTOM_RESET_HARDWARE) {
DEBUG_PORT.setDebugOutput(true);
}
#endif
#ifdef SONOFF_DUAL
#elif defined(SERIAL_BAUDRATE)
Serial.begin(SERIAL_BAUDRATE);
#endif
#if not EMBEDDED_WEB
SPIFFS.begin();
#endif
}
void hardwareLoop() {
@ -212,6 +215,9 @@ void setup() {
mqttSetup();
ntpSetup();
#ifdef SONOFF_RFBRIDGE
rfbSetup();
#endif
#if ENABLE_I2C
i2cSetup();
#endif
@ -266,9 +272,12 @@ void loop() {
#if ENABLE_FAUXMO
fauxmoLoop();
#endif
#ifndef SONOFF_DUAL
#if !defined(SONOFF_DUAL) & !defined(SONOFF_RFBRIDGE)
settingsLoop();
#endif
#ifdef SONOFF_RFBRIDGE
rfbLoop();
#endif
#if ENABLE_NOFUSS
nofussLoop();
#endif


+ 8
- 0
code/espurna/hardware.ino View File

@ -284,6 +284,14 @@ void hwUpwardsCompatibility() {
setSetting("ch1Logic", 0);
#endif
#ifdef SONOFF_RFBRIDGE
setSetting("board", 26);
setSetting("ledGPIO", 1, 13);
setSetting("ledLogic", 1, 1);
setSetting("btnGPIO", 1, 0);
setSetting("relayProvider", RELAY_PROVIDER_RFBRIDGE);
#endif
saveSettings();
}

+ 2
- 3
code/espurna/mqtt.ino View File

@ -227,14 +227,13 @@ void _mqttOnMessage(char* topic, char* payload, unsigned int len) {
char message[len + 1];
strlcpy(message, (char *) payload, len + 1);
DEBUG_MSG_P(PSTR("[MQTT] Received %s => %s"), topic, message);
#if MQTT_SKIP_RETAINED
if (millis() - mqttConnectedAt < MQTT_SKIP_TIME) {
DEBUG_MSG_P(PSTR(" - SKIPPED\n"));
DEBUG_MSG_P(PSTR("[MQTT] Received %s => %s - SKIPPED\n"), topic, message);
return;
}
#endif
DEBUG_MSG_P(PSTR("\n"));
DEBUG_MSG_P(PSTR("[MQTT] Received %s => %s\n"), topic, message);
// Send message event to subscribers
for (unsigned char i = 0; i < _mqtt_callbacks.size(); i++) {


+ 26
- 9
code/espurna/relay.ino View File

@ -20,6 +20,7 @@ typedef struct {
unsigned long delay_off;
unsigned int floodWindowStart;
unsigned char floodWindowChanges;
bool scheduled;
unsigned int scheduledStatusTime;
bool scheduledStatus;
bool scheduledReport;
@ -40,6 +41,10 @@ void relayProviderStatus(unsigned char id, bool status) {
if (id >= _relays.size()) return;
#if RELAY_PROVIDER == RELAY_PROVIDER_RFBRIDGE
rfbStatus(id, status);
#endif
#if RELAY_PROVIDER == RELAY_PROVIDER_DUAL
_dual_status ^= (1 << id);
Serial.flush();
@ -65,6 +70,10 @@ bool relayProviderStatus(unsigned char id) {
if (id >= _relays.size()) return false;
#if RELAY_PROVIDER == RELAY_PROVIDER_RFBRIDGE
return _relays[id].scheduledStatus;
#endif
#if RELAY_PROVIDER == RELAY_PROVIDER_DUAL
return ((_dual_status & (1 << id)) > 0);
#endif
@ -143,7 +152,9 @@ bool relayStatus(unsigned char id, bool status, bool report) {
bool changed = false;
#if TRACK_RELAY_STATUS
if (relayStatus(id) != status) {
#endif
unsigned int currentTime = millis();
unsigned int floodWindowEnd = _relays[id].floodWindowStart + 1000 * RELAY_FLOOD_WINDOW;
@ -170,6 +181,7 @@ bool relayStatus(unsigned char id, bool status, bool report) {
}
_relays[id].scheduled = true;
_relays[id].scheduledStatus = status;
if (report) _relays[id].scheduledReport = true;
@ -179,7 +191,9 @@ bool relayStatus(unsigned char id, bool status, bool report) {
changed = true;
#if TRACK_RELAY_STATUS
}
#endif
return changed;
}
@ -401,16 +415,14 @@ void relayInfluxDB(unsigned char id) {
void relaySetup() {
#if defined(SONOFF_DUAL)
// Two dummy relays for the dual
_relays.push_back((relay_t) {0, 0, 0, RELAY1_DELAY_ON, RELAY1_DELAY_OFF});
_relays.push_back((relay_t) {0, 0, 0, RELAY2_DELAY_ON, RELAY2_DELAY_OFF});
#elif defined(AI_LIGHT) | defined(LED_CONTROLLER) | defined(H801_LED_CONTROLLER)
// Dummy relays for AI Light, Magic Home LED Controller, H801,
// Sonoff Dual and Sonoff RF Bridge
#ifdef DUMMY_RELAY_COUNT
// One dummy relay for the AI Thinker Light & Magic Home and H801 led controllers
_relays.push_back((relay_t) {0, 0, 0, RELAY1_DELAY_ON, RELAY1_DELAY_OFF});
for (unsigned char i=0; i < DUMMY_RELAY_COUNT; i++) {
_relays.push_back((relay_t) {0, 0});
_relays[i].scheduled = false;
}
#else
@ -455,7 +467,11 @@ void relayLoop(void) {
unsigned int currentTime = millis();
bool status = _relays[id].scheduledStatus;
#if TRACK_RELAY_STATUS
if (relayStatus(id) != status && currentTime >= _relays[id].scheduledStatusTime) {
#else
if (_relays[id].scheduled && currentTime >= _relays[id].scheduledStatusTime) {
#endif
DEBUG_MSG_P(PSTR("[RELAY] #%d set to %s\n"), id, status ? "ON" : "OFF");
@ -487,6 +503,7 @@ void relayLoop(void) {
relayInfluxDB(id);
#endif
_relays[id].scheduled = false;
_relays[id].scheduledReport = false;
}


+ 307
- 0
code/espurna/rfbridge.ino View File

@ -0,0 +1,307 @@
/*
ITEAD RF BRIDGE MODULE
Copyright (C) 2017 by Xose Pérez <xose dot perez at gmail dot com>
*/
#ifdef SONOFF_RFBRIDGE
// -----------------------------------------------------------------------------
// DEFINITIONS
// -----------------------------------------------------------------------------
#define RF_MESSAGE_SIZE 9
#define RF_CODE_START 0xAA
#define RF_CODE_ACK 0xA0
#define RF_CODE_LEARN 0xA1
#define RF_CODE_LEARN_KO 0xA2
#define RF_CODE_LEARN_OK 0xA3
#define RF_CODE_RFIN 0xA4
#define RF_CODE_RFOUT 0xA5
#define RF_CODE_STOP 0x55
// -----------------------------------------------------------------------------
// GLOBALS TO THE MODULE
// -----------------------------------------------------------------------------
unsigned char _uartbuf[RF_MESSAGE_SIZE+3] = {0};
unsigned char _uartpos = 0;
unsigned char _learnId = 0;
bool _learnStatus = true;
bool _rfbin = false;
// -----------------------------------------------------------------------------
// PRIVATES
// -----------------------------------------------------------------------------
void _rfbAck() {
DEBUG_MSG_P(PSTR("[RFBRIDGE] 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 _rfbLearn() {
DEBUG_MSG_P(PSTR("[RFBRIDGE] Sending LEARN\n"));
Serial.println();
Serial.write(RF_CODE_START);
Serial.write(RF_CODE_LEARN);
Serial.write(RF_CODE_STOP);
Serial.flush();
Serial.println();
char wsb[100];
sprintf_P(wsb, PSTR("{\"action\": \"rfbLearn\", \"data\":{\"id\": %d, \"status\": %d}}"), _learnId, _learnStatus ? 1 : 0);
wsSend(wsb);
}
void _rfbSend(byte * message) {
Serial.println();
Serial.write(RF_CODE_START);
Serial.write(RF_CODE_RFOUT);
for (unsigned char j=0; j<RF_MESSAGE_SIZE; j++) {
Serial.write(message[j]);
}
Serial.write(RF_CODE_STOP);
Serial.flush();
Serial.println();
}
void _rfbSend(byte * message, int times) {
char buffer[RF_MESSAGE_SIZE];
_rfbToChar(message, buffer);
DEBUG_MSG_P(PSTR("[RFBRIDGE] Sending MESSAGE '%s' %d time(s)\n"), buffer, times);
for (int i=0; i<times; i++) {
if (i>0) {
unsigned long start = millis();
while (millis() - start < RF_SEND_DELAY) delay(1);
}
_rfbSend(message);
}
}
void _rfbDecode() {
byte action = _uartbuf[0];
char buffer[RF_MESSAGE_SIZE * 2 + 1] = {0};
DEBUG_MSG_P(PSTR("[RFBRIDGE] Action 0x%02X\n"), action);
if (action == RF_CODE_LEARN_KO) {
_rfbAck();
DEBUG_MSG_P(PSTR("[RFBRIDGE] Learn timeout\n"));
wsSend("{\"action\": \"rfbTimeout\"}");
}
if (action == RF_CODE_LEARN_OK || action == RF_CODE_RFIN) {
_rfbToChar(&_uartbuf[1], buffer);
mqttSend(MQTT_TOPIC_RFIN, buffer);
_rfbAck();
}
if (action == RF_CODE_LEARN_OK) {
DEBUG_MSG_P(PSTR("[RFBRIDGE] Learn success\n"));
rfbStore(_learnId, _learnStatus, buffer);
// Websocket update
char wsb[100];
sprintf_P(wsb, PSTR("{\"rfb\":[{\"id\": %d, \"status\": %d, \"data\": \"%s\"}]}"), _learnId, _learnStatus ? 1 : 0, buffer);
wsSend(wsb);
}
if (action == RF_CODE_RFIN) {
DEBUG_MSG_P(PSTR("[RFBRIDGE] Forward message '%s'\n"), buffer);
// Look for the code
unsigned char id, status;
bool found = false;
for (id=0; id<relayCount(); id++) {
for (status=0; status<2; status++) {
String code = rfbRetrieve(id, status == 1);
if (code.length()) {
if (code.endsWith(&buffer[12])) {
found = true;
break;
}
}
}
if (found) break;
}
if (found) {
_rfbin = true;
relayStatus(id, status == 1);
}
}
}
void _rfbReceive() {
static bool receiving = false;
while (Serial.available()) {
yield();
byte c = Serial.read();
//DEBUG_MSG_P(PSTR("[RFBRIDGE] Received 0x%02X\n"), c);
if (receiving) {
if (c == RF_CODE_STOP) {
_rfbDecode();
receiving = false;
} else {
_uartbuf[_uartpos++] = c;
}
} else if (c == RF_CODE_START) {
_uartpos = 0;
receiving = true;
}
}
}
bool _rfbCompare(const char * code1, const char * code2) {
return strcmp(&code1[12], &code2[12]) == 0;
}
bool _rfbSameOnOff(unsigned char id) {
return _rfbCompare(rfbRetrieve(id, true).c_str(), rfbRetrieve(id, false).c_str());
}
/*
From an hexa char array ("A220EE...") to a byte array (half the size)
*/
bool _rfbToArray(const char * in, byte * out) {
if (strlen(in) != RF_MESSAGE_SIZE * 2) return false;
char tmp[3] = {0};
for (unsigned char p = 0; p<RF_MESSAGE_SIZE; p++) {
memcpy(tmp, &in[p*2], 2);
out[p] = strtol(tmp, NULL, 16);
}
return true;
}
/*
From a byte array to an hexa char array ("A220EE...", double the size)
*/
bool _rfbToChar(byte * in, char * out) {
for (unsigned char p = 0; p<RF_MESSAGE_SIZE; p++) {
sprintf(&out[p*2], "%02X", in[p]);
}
return true;
}
void _rfbMqttCallback(unsigned int type, const char * topic, const char * payload) {
if (type == MQTT_CONNECT_EVENT) {
char buffer[strlen(MQTT_TOPIC_RFLEARN) + 3];
sprintf(buffer, "%s/+", MQTT_TOPIC_RFLEARN);
mqttSubscribe(buffer);
mqttSubscribe(MQTT_TOPIC_RFOUT);
}
if (type == MQTT_MESSAGE_EVENT) {
// Match topic
String t = mqttSubtopic((char *) topic);
// Check if should go into learn mode
if (t.startsWith(MQTT_TOPIC_RFLEARN)) {
_learnId = t.substring(strlen(MQTT_TOPIC_RFLEARN)+1).toInt();
if (_learnId >= relayCount()) {
DEBUG_MSG_P(PSTR("[RFBRIDGE] Wrong learnID (%d)\n"), _learnId);
return;
}
_learnStatus = (char)payload[0] != '0';
_rfbLearn();
}
if (t.equals(MQTT_TOPIC_RFOUT)) {
byte message[RF_MESSAGE_SIZE];
if (_rfbToArray(payload, message)) {
_rfbSend(message, 1);
}
}
}
}
// -----------------------------------------------------------------------------
// PUBLIC
// -----------------------------------------------------------------------------
void rfbStore(unsigned char id, bool status, const char * code) {
DEBUG_MSG_P(PSTR("[RFBRIDGE] Storing %d-%s => '%s'\n"), id, status ? "ON" : "OFF", code);
char key[8] = {0};
sprintf(key, "rfb%d%s", id, status ? "on" : "off");
setSetting(key, code);
}
String rfbRetrieve(unsigned char id, bool status) {
char key[8] = {0};
sprintf(key, "rfb%d%s", id, status ? "on" : "off");
return getSetting(key);
}
void rfbStatus(unsigned char id, bool status) {
String value = rfbRetrieve(id, status);
if (value.length() > 0) {
bool same = _rfbSameOnOff(id);
byte message[RF_MESSAGE_SIZE];
_rfbToArray(value.c_str(), message);
unsigned char times = RF_SEND_TIMES;
if (same) times = _rfbin ? 0 : 1;
_rfbSend(message, times);
}
}
void rfbLearn(unsigned char id, bool status) {
_learnId = id;
_learnStatus = status;
_rfbLearn();
}
void rfbForget(unsigned char id, bool status) {
char key[8] = {0};
sprintf(key, "rfb%d%s", id, status ? "on" : "off");
delSetting(key);
// Websocket update
char wsb[100];
sprintf_P(wsb, PSTR("{\"rfb\":[{\"id\": %d, \"status\": %d, \"data\": \"\"}]}"), id, status ? 1 : 0);
wsSend(wsb);
}
// -----------------------------------------------------------------------------
// SETUP & LOOP
// -----------------------------------------------------------------------------
void rfbSetup() {
mqttRegister(_rfbMqttCallback);
}
void rfbLoop() {
_rfbReceive();
}
#endif

+ 31
- 2
code/espurna/web.ino View File

@ -92,6 +92,21 @@ void _wsParse(uint32_t client_id, uint8_t * payload, size_t length) {
ESP.restart();
}
#ifdef SONOFF_RFBRIDGE
if (action.equals("rfblearn") && root.containsKey("data")) {
JsonObject& data = root["data"];
rfbLearn(data["id"], data["status"]);
}
if (action.equals("rfbforget") && root.containsKey("data")) {
JsonObject& data = root["data"];
rfbForget(data["id"], data["status"]);
}
if (action.equals("rfbsend") && root.containsKey("data")) {
JsonObject& data = root["data"];
rfbStore(data["id"], data["status"], data["data"].as<const char*>());
}
#endif
if (action.equals("restore") && root.containsKey("data")) {
JsonObject& data = root["data"];
@ -129,7 +144,7 @@ void _wsParse(uint32_t client_id, uint8_t * payload, size_t length) {
if (data.containsKey("status")) {
bool state = (strcmp(data["status"], "1") == 0);
bool status = (strcmp(data["status"], "1") == 0);
unsigned int relayID = 0;
if (data.containsKey("id")) {
@ -137,7 +152,7 @@ void _wsParse(uint32_t client_id, uint8_t * payload, size_t length) {
relayID = value.toInt();
}
relayStatus(relayID, state);
relayStatus(relayID, status);
}
@ -580,6 +595,20 @@ void _wsStart(uint32_t client_id) {
root["powPowerFactor"] = String(getPowerFactor(), 2);
#endif
#ifdef SONOFF_RFBRIDGE
root["rfbVisible"] = 1;
root["rfbCount"] = relayCount();
JsonArray& rfb = root.createNestedArray("rfb");
for (byte id=0; id<relayCount(); id++) {
for (byte status=0; status<2; status++) {
JsonObject& node = rfb.createNestedObject();
node["id"] = id;
node["status"] = status;
node["data"] = rfbRetrieve(id, status == 1);
}
}
#endif
root["maxNetworks"] = WIFI_MAX_NETWORKS;
JsonArray& wifi = root.createNestedArray("wifi");
for (byte i=0; i<WIFI_MAX_NETWORKS; i++) {


+ 21
- 3
code/html/custom.css View File

@ -46,7 +46,8 @@
background: #1f8dd6;
}
.button-reset,
.button-reconnect {
.button-reconnect,
.button-rfb-forget {
background: rgb(202, 60, 60);
}
.button-upgrade {
@ -58,13 +59,15 @@
background: rgb(0, 202, 0);
margin-left: 5px;
}
.button-add-network {
.button-add-network,
.button-rfb-learn {
background: rgb(28, 184, 65);
}
.button-del-network {
background: rgb(202, 60, 60);
}
.button-more-network {
.button-more-network,
.button-rfb-send {
background: rgb(223, 117, 20);
}
.button-settings-backup,
@ -164,4 +167,19 @@ div.state {
border: 0px;
padding: 0px;
margin-bottom: -4px;
#panel-rfb fieldset {
margin: 10px 2px;
padding: 20px;
}
#panel-rfb input {
margin-right: 5px;
}
#panel-rfb label {
padding-top: 5px;
}
#panel-rfb input {
text-align: center;
}

+ 60
- 0
code/html/custom.js View File

@ -362,6 +362,43 @@ function initChannels(num) {
}
function addRfbNode() {
var numNodes = $("#rfbNodes > fieldset").length;
var template = $("#rfbNodeTemplate").children();
var line = $(template).clone();
var status = true;
$("span", line).html(numNodes+1);
$(line).find("input").each(function() {
$(this).attr("data_id", numNodes);
$(this).attr("data_status", status ? 1 : 0);
status = !status;
});
$(line).find(".button-rfb-learn").on('click', rfbLearn);
$(line).find(".button-rfb-forget").on('click', rfbForget);
$(line).find(".button-rfb-send").on('click', rfbSend);
line.appendTo("#rfbNodes");
return line;
}
function rfbLearn() {
var parent = $(this).parents(".pure-g");
var input = $("input", parent);
websock.send(JSON.stringify({'action': 'rfblearn', 'data' : {'id' : input.attr("data_id"), 'status': input.attr("data_status")}}));
}
function rfbForget() {
var parent = $(this).parents(".pure-g");
var input = $("input", parent);
websock.send(JSON.stringify({'action': 'rfbforget', 'data' : {'id' : input.attr("data_id"), 'status': input.attr("data_status")}}));
}
function rfbSend() {
var parent = $(this).parents(".pure-g");
var input = $("input", parent);
websock.send(JSON.stringify({'action': 'rfbsend', 'data' : {'id' : input.attr("data_id"), 'status': input.attr("data_status"), 'data': input.val()}}));
}
function forgetCredentials() {
@ -417,10 +454,33 @@ function processData(data) {
}, 1000);
}
if (data.action == "rfbLearn") {
// Nothing to do?
}
if (data.action == "rfbTimeout") {
// Nothing to do?
}
return;
}
if (key == "rfbCount") {
for (var i=0; i<data.rfbCount; i++) addRfbNode();
return;
}
if (key == "rfb") {
var nodes = data.rfb;
for (var i in nodes) {
var node = nodes[i];
var element = $("input[name=rfbcode][data_id=" + node["id"] + "][data_status=" + node["status"] + "]");
if (element.length) element.val(node["data"]);
}
return;
}
if (key == "color") {
initColor();
$("input[name='color']").wheelColorPicker('setValue', data[key], true);


+ 49
- 0
code/html/index.html View File

@ -115,6 +115,10 @@
<a href="#" class="pure-menu-link" data="panel-power">POWER</a>
</li>
<li class="pure-menu-item module module-rfb">
<a href="#" class="pure-menu-link" data="panel-rfb">RFBRIDGE</a>
</li>
<li class="pure-menu-item">
<a href="#" class="pure-menu-link" data="panel-admin">ADMIN</a>
</li>
@ -743,12 +747,57 @@
</div>
</form>
<div class="panel" id="panel-rfb">
<div class="header">
<h1>RFBRIDGE</h1>
<h2>
Sonoff 433 RF Bridge Configuration<br /><br />
To learn a new code click <strong>LEARN</strong>, the Sonoff RFBridge will beep, then press a button on the remote, the RFBridge will then double beep and the new code should show up. 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 (all codes must be 18 characters long) 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.
</h2>
</div>
<div class="page">
<div id="rfbNodes" />
</div>
</div>
</div> <!-- content -->
</div> <!-- layout -->
<!-- Templates -->
<div id="rfbNodeTemplate" class="template">
<fieldset>
<legend>&nbsp;Switch <span></span>&nbsp;</legend>
<div class="pure-g">
<label class="pure-u-1-2 pure-u-sm-1-4">Switch ON</label>
<input class="pure-u-1-2 pure-u-sm-1-3" type="text" maxlength="18" name="rfbcode" data_id="1" data_status="1" />
<div class="pure-u-1-3 pure-u-md-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-md-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-md-1-8"><button type="button" class="pure-u-23-24 pure-button button-rfb-forget">FORGET</button></div>
</div>
<div class="pure-g">
<label class="pure-u-1-2 pure-u-sm-1-4">Switch OFF</label>
<input class="pure-u-1-2 pure-u-sm-1-3" type="text" maxlength="18" name="rfbcode" data_id="1" data_status="0" />
<div class="pure-u-1-3 pure-u-md-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-md-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-md-1-8"><button type="button" class="pure-u-23-24 pure-button button-rfb-forget">FORGET</button></div>
</div>
</fieldset>
</div>
<div id="networkTemplate" class="template">
<div class="pure-g">


+ 21
- 0
code/platformio.ini View File

@ -262,6 +262,27 @@ upload_speed = 115200
upload_port = "192.168.4.1"
upload_flags = --auth=fibonacci --port 8266
[env:rfbridge-debug]
platform = espressif8266
framework = arduino
board = esp01_1m
board_flash_mode = dout
lib_deps = ${common.lib_deps}
lib_ignore = ${common.lib_ignore}
build_flags = ${common.build_flags_1m} -DSONOFF_RFBRIDGE
[env:rfbridge-debug-ota]
platform = espressif8266
framework = arduino
board = esp01_1m
board_flash_mode = dout
lib_deps = ${common.lib_deps}
lib_ignore = ${common.lib_ignore}
build_flags = ${common.build_flags_1m} -DSONOFF_RFBRIDGE
upload_speed = 115200
upload_port = "192.168.4.1"
upload_flags = --auth=Algernon1 --port 8266
[env:1ch-inching-debug]
platform = espressif8266
framework = arduino


Loading…
Cancel
Save