Browse Source

Domoticz support

fastled
Xose Pérez 8 years ago
parent
commit
523fbca115
8 changed files with 207 additions and 6 deletions
  1. +8
    -0
      code/espurna/config/general.h
  2. +78
    -0
      code/espurna/domoticz.ino
  3. +3
    -0
      code/espurna/espurna.ino
  4. +4
    -0
      code/espurna/relay.ino
  5. +32
    -0
      code/espurna/web.ino
  6. +1
    -1
      code/html/custom.css
  7. +30
    -0
      code/html/custom.js
  8. +51
    -5
      code/html/index.html

+ 8
- 0
code/espurna/config/general.h View File

@ -86,6 +86,14 @@
#define MQTT_USE_SETTER "" #define MQTT_USE_SETTER ""
// -----------------------------------------------------------------------------
// DOMOTICZ
// -----------------------------------------------------------------------------
#define ENABLE_DOMOTICZ 1
#define DOMOTICZ_IN_TOPIC "domoticz/in"
#define DOMOTICZ_OUT_TOPIC "domoticz/out"
// ----------------------------------------------------------------------------- // -----------------------------------------------------------------------------
// NTP // NTP
// ----------------------------------------------------------------------------- // -----------------------------------------------------------------------------


+ 78
- 0
code/espurna/domoticz.ino View File

@ -0,0 +1,78 @@
/*
ESPurna
DOMOTICZ MODULE
Copyright (C) 2016 by Xose Pérez <xose dot perez at gmail dot com>
*/
#if ENABLE_DOMOTICZ
#include <Hash.h>
#include <ArduinoJson.h>
void domoticzMQTTCallback(unsigned int type, const char * topic, const char * payload) {
String dczTopicOut = getSetting("dczTopicOut", DOMOTICZ_OUT_TOPIC);
if (type == MQTT_CONNECT_EVENT) {
mqttSubscribeRaw(dczTopicOut.c_str());
}
if (type == MQTT_MESSAGE_EVENT) {
// Check topic
if (dczTopicOut.equals(topic)) {
// Parse response
DynamicJsonBuffer jsonBuffer;
JsonObject& root = jsonBuffer.parseObject((char *) payload);
if (!root.success()) {
DEBUG_MSG("[DOMOTICZ] Error parsing data\n");
return;
}
// IDX
unsigned long idx = root["idx"];
int relayID = domoticzRelay(idx);
if (relayID >= 0) {
unsigned long value = root["nvalue"];
DEBUG_MSG("[DOMOTICZ] Received value %d for IDX %d\n", value, idx);
relayStatus(relayID, value == 1);
}
}
}
}
int domoticzIdx(unsigned int relayID) {
return getSetting("dczIdx" + String(relayID)).toInt();
}
int domoticzRelay(unsigned int idx) {
for (int relayID=0; relayID<relayCount(); relayID++) {
if (domoticzIdx(relayID) == idx) {
return relayID;
}
}
return -1;
}
void domoticzSend(unsigned int relayID) {
unsigned int idx = domoticzIdx(relayID);
if (idx > 0) {
unsigned int value = relayStatus(relayID) ? 1 : 0;
char payload[45];
sprintf(payload, "{\"idx\": %d, \"nvalue\": %d, \"svalue\": \"\"}", idx, value);
mqttSendRaw(getSetting("dczTopicIn", DOMOTICZ_IN_TOPIC).c_str(), payload);
}
}
void domoticzSetup() {
mqttRegister(domoticzMQTTCallback);
}
#endif

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

@ -125,6 +125,9 @@ void setup() {
webSetup(); webSetup();
ntpSetup(); ntpSetup();
#if ENABLE_DOMOTICZ
domoticzSetup();
#endif
#if ENABLE_FAUXMO #if ENABLE_FAUXMO
fauxmoSetup(); fauxmoSetup();
#endif #endif


+ 4
- 0
code/espurna/relay.ino View File

@ -92,6 +92,10 @@ bool relayStatus(unsigned char id, bool status, bool report) {
relaySave(); relaySave();
} }
#ifdef ENABLE_DOMOTICZ
domoticzSend(id);
#endif
} }
if (report) relayMQTT(id); if (report) relayMQTT(id);


+ 32
- 0
code/espurna/web.ino View File

@ -94,6 +94,7 @@ void _wsParse(uint32_t client_id, uint8_t * payload, size_t length) {
bool fauxmoEnabled = false; bool fauxmoEnabled = false;
#endif #endif
unsigned int network = 0; unsigned int network = 0;
unsigned int dczIdx = 0;
String adminPass; String adminPass;
for (unsigned int i=0; i<config.size(); i++) { for (unsigned int i=0; i<config.size(); i++) {
@ -108,6 +109,24 @@ void _wsParse(uint32_t client_id, uint8_t * payload, size_t length) {
continue; continue;
} }
#else
if (key.startsWith("pow")) continue;
#endif
#if ENABLE_DOMOTICZ
if (key == "dczIdx") {
if (dczIdx >= relayCount()) continue;
key = key + String(dczIdx);
++dczIdx;
}
#else
if (key.startsWith("dcz")) continue;
#endif #endif
// Check password // Check password
@ -242,6 +261,19 @@ void _wsStart(uint32_t client_id) {
root["apiEnabled"] = getSetting("apiEnabled").toInt() == 1; root["apiEnabled"] = getSetting("apiEnabled").toInt() == 1;
root["apiKey"] = getSetting("apiKey"); root["apiKey"] = getSetting("apiKey");
#if ENABLE_DOMOTICZ
root["dczVisible"] = 1;
root["dczTopicIn"] = getSetting("dczTopicIn", DOMOTICZ_IN_TOPIC);
root["dczTopicOut"] = getSetting("dczTopicOut", DOMOTICZ_OUT_TOPIC);
JsonArray& dczIdx = root.createNestedArray("dczIdx");
for (byte i=0; i<relayCount(); i++) {
dczIdx.add(domoticzIdx(i));
}
#endif
#if ENABLE_FAUXMO #if ENABLE_FAUXMO
root["fauxmoVisible"] = 1; root["fauxmoVisible"] = 1;
root["fauxmoEnabled"] = getSetting("fauxmoEnabled", FAUXMO_ENABLED).toInt() == 1; root["fauxmoEnabled"] = getSetting("fauxmoEnabled", FAUXMO_ENABLED).toInt() == 1;


+ 1
- 1
code/html/custom.css View File

@ -61,6 +61,6 @@ div.hint {
.module { .module {
display: none; display: none;
} }
#relayTemplate {
.template {
display: none; display: none;
} }

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

@ -84,6 +84,23 @@ function createRelays(count) {
} }
function createIdxs(count) {
var current = $("#idxs > div").length;
if (current > 0) return;
var template = $("#idxTemplate .pure-g")[0];
for (var id=0; id<count; id++) {
var line = $(template).clone();
$(line).find("input").each(function() {
$(this).attr("data", id).attr("tabindex", 43+id);
});
if (count > 1) $(".id", line).html(" " + id);
line.appendTo("#idxs");
}
}
function processData(data) { function processData(data) {
// title // title
@ -162,6 +179,19 @@ function processData(data) {
} }
// Domoticz
if (key == "dczIdx") {
var idxs = data.dczIdx;
createIdxs(idxs.length);
for (var i in idxs) {
var element = $(".dczIdx[data=" + i + "]");
if (element.length > 0) element.val(idxs[i]);
}
return;
}
// Messages // Messages
if (key == "message") { if (key == "message") {


+ 51
- 5
code/html/index.html View File

@ -52,6 +52,10 @@
<a href="#" class="pure-menu-link" data="panel-mqtt">MQTT</a> <a href="#" class="pure-menu-link" data="panel-mqtt">MQTT</a>
</li> </li>
<li class="pure-menu-item module module-dcz">
<a href="#" class="pure-menu-link" data="panel-domoticz">DOMOTICZ</a>
</li>
<li class="pure-menu-item module module-pow"> <li class="pure-menu-item module module-pow">
<a href="#" class="pure-menu-link" data="panel-power">POWER</a> <a href="#" class="pure-menu-link" data="panel-power">POWER</a>
</li> </li>
@ -139,14 +143,13 @@
<div id="relays"> <div id="relays">
</div> </div>
<div id="relayTemplate">
<div id="relayTemplate" class="template">
<div class="pure-g"> <div class="pure-g">
<div class="pure-u-1 pure-u-sm-1-4"><label >Relay<span class="relay_id"></span> Status</label></div> <div class="pure-u-1 pure-u-sm-1-4"><label >Relay<span class="relay_id"></span> Status</label></div>
<div class="pure-u-1 pure-u-sm-1-4"><input type="checkbox" class="relayStatus" data="0" /></div> <div class="pure-u-1 pure-u-sm-1-4"><input type="checkbox" class="relayStatus" data="0" /></div>
</div> </div>
</div> </div>
</fieldset> </fieldset>
</form> </form>
@ -335,10 +338,53 @@
</div> </div>
<div class="pure-g"> <div class="pure-g">
<label class="pure-u-1 pure-u-md-1-4" for="mqttTopic">MQTT Topic</label>
<label class="pure-u-1 pure-u-md-1-4" for="mqttTopic">MQTT Root Topic</label>
<input class="pure-u-1 pure-u-md-3-4" name="mqttTopic" type="text" size="20" tabindex="14" /> <input class="pure-u-1 pure-u-md-3-4" name="mqttTopic" type="text" size="20" tabindex="14" />
<div class="pure-u-0 pure-u-md-1-4">&nbsp;</div> <div class="pure-u-0 pure-u-md-1-4">&nbsp;</div>
<div class="pure-u-1 pure-u-md-3-4 hint">Send a 0 or a 1 as a payload to the provided topic below to switch it on or off. You can also send a 2 to toggle its current state. The switch will also report its current open/close status to the same topic and its IP address, hertbeat, firmware version and file system version to the topic you define plus "/ip", "/heartbeat", "/version" and "/fsversion" respectively. </div>
<div class="pure-u-1 pure-u-md-3-4 hint">This is the root topic for this device. The {identifier} placeholder will be replaces by the device hostname.<br />
- <strong>&lt;root&gt;/relay/#</strong> Send a 0 or a 1 as a payload to this topic to switch it on or off. You can also send a 2 to toggle its current state. Replace # with the relay ID (starting from 0). If the board has only one relay it will be 0.<br />
- <strong>&lt;root&gt;/led/#</strong> Send a 0 or a 1 as a payload to this topic to set the onboard LED to the given state, send a 3 to turn it back to WIFI indicator. Replace # with the LED ID (starting from 0). If the board has only one LED it will be 0.<br />
- <strong>&lt;root&gt;/ip</strong> The device will report to this topic its IP.<br />
- <strong>&lt;root&gt;/heartbeat</strong> The device will report to this topic every few minutes.<br />
- <strong>&lt;root&gt;/version</strong> The device will report to this topic its firmware version on boot.<br />
</div>
</fieldset>
</div>
</div>
<div class="panel" id="panel-domoticz">
<div class="header">
<h1>DOMOTICZ</h1>
<h2>
Configure the connection to your Domoticz server.
</h2>
</div>
<div class="page">
<fieldset>
<div class="pure-g">
<label class="pure-u-1 pure-u-md-1-4" for="dczTopicIn">Domoticz IN Topic</label>
<input class="pure-u-1 pure-u-md-3-4" name="dczTopicIn" type="text" tabindex="41" placeholder="domoticz/in" />
</div>
<div class="pure-g">
<label class="pure-u-1 pure-u-md-1-4" for="dczTopicOut">Domoticz OUT Topic</label>
<input class="pure-u-1 pure-u-md-3-4" name="dczTopicOut" type="text" tabindex="42" placeholder="domoticz/out" />
</div>
<div id="idxs">
</div>
<div id="idxTemplate" class="template">
<div class="pure-g">
<label class="pure-u-1 pure-u-sm-1-4">Relay<span class="id"></span> IDX</label>
<input class="pure-u-1 pure-u-sm-1-4 dczIdx" name="dczIdx" type="number" tabindex="0" data="0" /></div>
</div>
</div> </div>
</fieldset> </fieldset>
@ -361,7 +407,7 @@
<div class="pure-g"> <div class="pure-g">
<label class="pure-u-1 pure-u-md-1-4" for="powExpectedPower">AC RMS Active Power</label> <label class="pure-u-1 pure-u-md-1-4" for="powExpectedPower">AC RMS Active Power</label>
<input class="pure-u-1 pure-u-md-3-4 powExpected" name="powExpectedPower" type="text" size="8" tabindex="40" placeholder="0" />
<input class="pure-u-1 pure-u-md-3-4 powExpected" name="powExpectedPower" type="text" size="8" tabindex="50" placeholder="0" />
<div class="pure-u-0 pure-u-md-1-4">&nbsp;</div> <div class="pure-u-0 pure-u-md-1-4">&nbsp;</div>
<div class="pure-u-1 pure-u-md-3-4 hint">If you are using a pure resistive load like a bulb this will be writen on it, otherwise use a socket multimeter to get this value.</div> <div class="pure-u-1 pure-u-md-3-4 hint">If you are using a pure resistive load like a bulb this will be writen on it, otherwise use a socket multimeter to get this value.</div>
</div> </div>


Loading…
Cancel
Save