From cf714106fbe152ab5e4164d32294dc96115b2014 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Xose=20P=C3=A9rez?= Date: Thu, 10 Aug 2017 15:31:15 +0200 Subject: [PATCH] RFBridge web intrface --- code/espurna/relay.ino | 2 +- code/espurna/rfbridge.ino | 58 ++++++++++++++++++++++++------------ code/espurna/web.ino | 33 +++++++++++++++++++-- code/html/custom.css | 26 ++++++++++++++-- code/html/custom.js | 62 +++++++++++++++++++++++++++++++++++++++ code/html/index.html | 44 +++++++++++++++++++++++++++ 6 files changed, 200 insertions(+), 25 deletions(-) diff --git a/code/espurna/relay.ino b/code/espurna/relay.ino index 5073b830..dd82440c 100644 --- a/code/espurna/relay.ino +++ b/code/espurna/relay.ino @@ -40,7 +40,7 @@ void relayProviderStatus(unsigned char id, bool status) { if (id >= _relays.size()) return; #if RELAY_PROVIDER == RELAY_PROVIDER_RFBRIDGE - rfbState(id, status); + rfbStatus(id, status); #endif #if RELAY_PROVIDER == RELAY_PROVIDER_DUAL diff --git a/code/espurna/rfbridge.ino b/code/espurna/rfbridge.ino index 53b59f0c..ed6a765c 100644 --- a/code/espurna/rfbridge.ino +++ b/code/espurna/rfbridge.ino @@ -29,7 +29,7 @@ Copyright (C) 2017 by Xose PĂ©rez unsigned char _uartbuf[RF_MESSAGE_SIZE+3] = {0}; unsigned char _uartpos = 0; unsigned char _learnId = 0; -bool _learnState = true; +bool _learnStatus = true; // ----------------------------------------------------------------------------- // PRIVATES @@ -46,6 +46,7 @@ void _rfbAck() { } void _rfbLearn() { + DEBUG_MSG_P(PSTR("[RFBRIDGE] Sending LEARN\n")); Serial.println(); Serial.write(RF_CODE_START); @@ -53,6 +54,11 @@ void _rfbLearn() { 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) { @@ -92,6 +98,7 @@ void _rfbDecode() { 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) { @@ -101,9 +108,15 @@ void _rfbDecode() { } if (action == RF_CODE_LEARN_OK) { - // TODO: notify websocket - _rfbStore(_learnId, _learnState, buffer); - DEBUG_MSG_P(PSTR("[RFBRIDGE] Learn success. Storing %d-%s => '%s'\n"), _learnId, _learnState ? "ON" : "OFF", buffer); + + 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) { @@ -111,11 +124,11 @@ void _rfbDecode() { DEBUG_MSG_P(PSTR("[RFBRIDGE] Forward message '%s'\n"), buffer); // Look for the code - unsigned char id, state; + unsigned char id, status; bool found = false; for (id=0; id '%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) { +String rfbRetrieve(unsigned char id, bool status) { char key[8] = {0}; sprintf(key, "rfb%d%s", id, status ? "on" : "off"); return getSetting(key); } -// ----------------------------------------------------------------------------- -// PUBLIC -// ----------------------------------------------------------------------------- - -void rfbState(unsigned char id, bool status) { - String value = _rfbRetrieve(id, status); - DEBUG_MSG_P(PSTR("[RFBRIDGE] Retrieving value for %d-%s => %s\n"), id, status ? "ON" : "OFF", value.c_str()); +void rfbStatus(unsigned char id, bool status) { + String value = rfbRetrieve(id, status); if (value.length() > 0) { byte message[RF_MESSAGE_SIZE]; _rfbToArray(value.c_str(), message); @@ -247,14 +260,21 @@ void rfbState(unsigned char id, bool status) { void rfbLearn(unsigned char id, bool status) { _learnId = id; - _learnState = status; + _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); + } // ----------------------------------------------------------------------------- diff --git a/code/espurna/web.ino b/code/espurna/web.ino index eb538741..99539d59 100644 --- a/code/espurna/web.ino +++ b/code/espurna/web.ino @@ -88,6 +88,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()); + } + #endif + if (action.equals("restore") && root.containsKey("data")) { JsonObject& data = root["data"]; @@ -125,7 +140,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")) { @@ -133,7 +148,7 @@ void _wsParse(uint32_t client_id, uint8_t * payload, size_t length) { relayID = value.toInt(); } - relayStatus(relayID, state); + relayStatus(relayID, status); } @@ -560,6 +575,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 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() { $.ajax({ 'method': 'GET', @@ -337,10 +376,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; iPOWER +
  • + RFBRIDGE +
  • +
  • ADMIN
  • @@ -707,12 +711,52 @@ +
    + +
    +

    RFBRIDGE

    +

    Sonoff 433 RF Bridge Configuration

    +
    + +
    + +
    + +
    +
    +
    +
    + +
    + +  Switch   + +
    + + +
    +
    +
    +
    + +
    + + +
    +
    +
    +
    + +
    + +
    +