Browse Source

Merge branch 'dev' of github.com:xoseperez/espurna into dev

master
Xose Pérez 5 years ago
parent
commit
78ebe98532
25 changed files with 22236 additions and 22138 deletions
  1. +7
    -1
      code/build.sh
  2. BIN
      code/espurna/data/index.all.html.gz
  3. BIN
      code/espurna/data/index.light.html.gz
  4. BIN
      code/espurna/data/index.lightfox.html.gz
  5. BIN
      code/espurna/data/index.rfbridge.html.gz
  6. BIN
      code/espurna/data/index.rfm69.html.gz
  7. BIN
      code/espurna/data/index.sensor.html.gz
  8. BIN
      code/espurna/data/index.small.html.gz
  9. BIN
      code/espurna/data/index.thermostat.html.gz
  10. +11
    -0
      code/espurna/espurna.ino
  11. +2
    -0
      code/espurna/homeassistant.ino
  12. +51
    -19
      code/espurna/light.ino
  13. +124
    -87
      code/espurna/mqtt.ino
  14. +3229
    -3223
      code/espurna/static/index.all.html.gz.h
  15. +3061
    -3056
      code/espurna/static/index.light.html.gz.h
  16. +2133
    -2132
      code/espurna/static/index.lightfox.html.gz.h
  17. +2443
    -2442
      code/espurna/static/index.rfbridge.html.gz.h
  18. +4142
    -4140
      code/espurna/static/index.rfm69.html.gz.h
  19. +2237
    -2236
      code/espurna/static/index.sensor.html.gz.h
  20. +2133
    -2132
      code/espurna/static/index.small.html.gz.h
  21. +2657
    -2656
      code/espurna/static/index.thermostat.html.gz.h
  22. +0
    -12
      code/espurna/ws.ino
  23. +2
    -2
      code/html/index.html
  24. +4
    -0
      code/platformio.ini
  25. BIN
      images/devices/generic-ag-l4-2.jpg

+ 7
- 1
code/build.sh View File

@ -112,12 +112,18 @@ build_webui() {
echo "--------------------------------------------------------------" echo "--------------------------------------------------------------"
echo "Building web interface..." echo "Building web interface..."
node node_modules/gulp/bin/gulp.js || exit node node_modules/gulp/bin/gulp.js || exit
# TODO: do something if webui files are different
# for now, just print in travis log
if ${TRAVIS:-false}; then
git --no-pager diff --stat
fi
} }
build_environments() { build_environments() {
echo "--------------------------------------------------------------" echo "--------------------------------------------------------------"
echo "Building firmware images..." echo "Building firmware images..."
mkdir -p ../firmware/espurna-$version
mkdir -p $destination/espurna-$version
for environment in $environments; do for environment in $environments; do
echo -n "* espurna-$version-$environment.bin --- " echo -n "* espurna-$version-$environment.bin --- "


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


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

@ -25,6 +25,7 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
std::vector<void (*)()> _loop_callbacks; std::vector<void (*)()> _loop_callbacks;
std::vector<void (*)()> _reload_callbacks; std::vector<void (*)()> _reload_callbacks;
bool _reload_config = false;
unsigned long _loop_delay = 0; unsigned long _loop_delay = 0;
// ----------------------------------------------------------------------------- // -----------------------------------------------------------------------------
@ -40,6 +41,10 @@ void espurnaRegisterReload(void (*callback)()) {
} }
void espurnaReload() { void espurnaReload() {
_reload_config = true;
}
void _espurnaReload() {
for (unsigned char i = 0; i < _reload_callbacks.size(); i++) { for (unsigned char i = 0; i < _reload_callbacks.size(); i++) {
(_reload_callbacks[i])(); (_reload_callbacks[i])();
} }
@ -228,6 +233,12 @@ void setup() {
void loop() { void loop() {
// Reload config before running any callbacks
if (_reload_config) {
_espurnaReload();
_reload_config = false;
}
// Call registered loop callbacks // Call registered loop callbacks
for (unsigned char i = 0; i < _loop_callbacks.size(); i++) { for (unsigned char i = 0; i < _loop_callbacks.size(); i++) {
(_loop_callbacks[i])(); (_loop_callbacks[i])();


+ 2
- 0
code/espurna/homeassistant.ino View File

@ -104,6 +104,8 @@ void _haSendSwitch(unsigned char i, JsonObject& config) {
if (lightHasColor()) { if (lightHasColor()) {
config["rgb_state_topic"] = mqttTopic(MQTT_TOPIC_COLOR_RGB, false); config["rgb_state_topic"] = mqttTopic(MQTT_TOPIC_COLOR_RGB, false);
config["rgb_command_topic"] = mqttTopic(MQTT_TOPIC_COLOR_RGB, true); config["rgb_command_topic"] = mqttTopic(MQTT_TOPIC_COLOR_RGB, true);
}
if (lightUseCCT()) {
config["color_temp_command_topic"] = mqttTopic(MQTT_TOPIC_MIRED, true); config["color_temp_command_topic"] = mqttTopic(MQTT_TOPIC_MIRED, true);
} }


+ 51
- 19
code/espurna/light.ino View File

@ -88,6 +88,11 @@ void _setRGBInputValue(unsigned char red, unsigned char green, unsigned char blu
_light_channel[2].inputValue = constrain(blue, 0, LIGHT_MAX_VALUE);; _light_channel[2].inputValue = constrain(blue, 0, LIGHT_MAX_VALUE);;
} }
void _setCCTInputValue(unsigned char warm, unsigned char cold) {
_light_channel[0].inputValue = constrain(warm, 0, LIGHT_MAX_VALUE);
_light_channel[1].inputValue = constrain(cold, 0, LIGHT_MAX_VALUE);
}
void _generateBrightness() { void _generateBrightness() {
double brightness = (double) _light_brightness / LIGHT_MAX_BRIGHTNESS; double brightness = (double) _light_brightness / LIGHT_MAX_BRIGHTNESS;
@ -278,7 +283,21 @@ void _fromHSV(const char * hsv) {
// https://github.com/stelgenhof/AiLight // https://github.com/stelgenhof/AiLight
void _fromKelvin(unsigned long kelvin) { void _fromKelvin(unsigned long kelvin) {
if (!_light_has_color) return;
if (!_light_has_color) {
if(!_light_use_cct) return;
_light_mireds = constrain(round(1000000UL / kelvin), LIGHT_MIN_MIREDS, LIGHT_MAX_MIREDS);
// This change the range from 153-500 to 0-347 so we get a value between 0 and 1 in the end.
double factor = ((double) _light_mireds - (double) LIGHT_COLDWHITE_MIRED)/((double) LIGHT_WARMWHITE_MIRED - (double) LIGHT_COLDWHITE_MIRED);
unsigned char warm = round(factor * LIGHT_MAX_VALUE);
unsigned char cold = round(((double) 1.0 - factor) * LIGHT_MAX_VALUE);
_setCCTInputValue(warm, cold);
return;
}
_light_mireds = constrain(round(1000000UL / kelvin), LIGHT_MIN_MIREDS, LIGHT_MAX_MIREDS); _light_mireds = constrain(round(1000000UL / kelvin), LIGHT_MIN_MIREDS, LIGHT_MAX_MIREDS);
@ -542,12 +561,15 @@ void _lightMQTTCallback(unsigned int type, const char * topic, const char * payl
mqttSubscribe(MQTT_TOPIC_BRIGHTNESS); mqttSubscribe(MQTT_TOPIC_BRIGHTNESS);
if (_light_has_color) { if (_light_has_color) {
mqttSubscribe(MQTT_TOPIC_MIRED);
mqttSubscribe(MQTT_TOPIC_KELVIN);
mqttSubscribe(MQTT_TOPIC_COLOR_RGB); mqttSubscribe(MQTT_TOPIC_COLOR_RGB);
mqttSubscribe(MQTT_TOPIC_COLOR_HSV); mqttSubscribe(MQTT_TOPIC_COLOR_HSV);
mqttSubscribe(MQTT_TOPIC_TRANSITION); mqttSubscribe(MQTT_TOPIC_TRANSITION);
} }
if (_light_has_color || _light_use_cct) {
mqttSubscribe(MQTT_TOPIC_MIRED);
mqttSubscribe(MQTT_TOPIC_KELVIN);
}
// Group color // Group color
if (mqtt_group_color.length() > 0) mqttSubscribeRaw(mqtt_group_color.c_str()); if (mqtt_group_color.length() > 0) mqttSubscribeRaw(mqtt_group_color.c_str());
@ -643,10 +665,14 @@ void lightMQTT() {
_toHSV(buffer, sizeof(buffer), true); _toHSV(buffer, sizeof(buffer), true);
mqttSend(MQTT_TOPIC_COLOR_HSV, buffer); mqttSend(MQTT_TOPIC_COLOR_HSV, buffer);
// Mireds
snprintf_P(buffer, sizeof(buffer), PSTR("%d"), _light_mireds);
mqttSend(MQTT_TOPIC_MIRED, buffer);
}
if (_light_has_color || _light_use_cct) {
// Mireds
snprintf_P(buffer, sizeof(buffer), PSTR("%d"), _light_mireds);
mqttSend(MQTT_TOPIC_MIRED, buffer);
} }
// Channels // Channels
@ -700,6 +726,10 @@ bool lightHasColor() {
return _light_has_color; return _light_has_color;
} }
bool lightUseCCT() {
return _light_use_cct;
}
void _lightComms(unsigned char mask) { void _lightComms(unsigned char mask) {
// Report color & brightness to MQTT broker // Report color & brightness to MQTT broker
@ -869,16 +899,16 @@ bool _lightWebSocketOnReceive(const char * key, JsonVariant& value) {
void _lightWebSocketStatus(JsonObject& root) { void _lightWebSocketStatus(JsonObject& root) {
if (_light_has_color) { if (_light_has_color) {
if (_light_use_cct) {
root["useCCT"] = _light_use_cct;
root["mireds"] = _light_mireds;
}
if (getSetting("useRGB", LIGHT_USE_RGB).toInt() == 1) { if (getSetting("useRGB", LIGHT_USE_RGB).toInt() == 1) {
root["rgb"] = lightColor(true); root["rgb"] = lightColor(true);
} else { } else {
root["hsv"] = lightColor(false); root["hsv"] = lightColor(false);
} }
} }
if (_light_use_cct) {
root["useCCT"] = _light_use_cct;
root["mireds"] = _light_mireds;
}
JsonArray& channels = root.createNestedArray("channels"); JsonArray& channels = root.createNestedArray("channels");
for (unsigned char id=0; id < _light_channel.size(); id++) { for (unsigned char id=0; id < _light_channel.size(); id++) {
channels.add(lightChannel(id)); channels.add(lightChannel(id));
@ -913,13 +943,15 @@ void _lightWebSocketOnAction(uint32_t client_id, const char * action, JsonObject
lightUpdate(true, true); lightUpdate(true, true);
} }
} }
if (_light_use_cct) {
if (strcmp(action, "mireds") == 0) {
_fromMireds(data["mireds"]);
lightUpdate(true, true);
}
}
} }
if (_light_use_cct) {
if (strcmp(action, "mireds") == 0) {
_fromMireds(data["mireds"]);
lightUpdate(true, true);
}
}
if (strcmp(action, "channel") == 0) { if (strcmp(action, "channel") == 0) {
if (data.containsKey("id") && data.containsKey("value")) { if (data.containsKey("id") && data.containsKey("value")) {
@ -1135,13 +1167,13 @@ void _lightConfigure() {
} }
_light_use_white = getSetting("useWhite", LIGHT_USE_WHITE).toInt() == 1; _light_use_white = getSetting("useWhite", LIGHT_USE_WHITE).toInt() == 1;
if (_light_use_white && (_light_channel.size() < 4)) {
if (_light_use_white && (_light_channel.size() < 4) && (_light_channel.size() != 2)) {
_light_use_white = false; _light_use_white = false;
setSetting("useWhite", _light_use_white); setSetting("useWhite", _light_use_white);
} }
_light_use_cct = getSetting("useCCT", LIGHT_USE_CCT).toInt() == 1; _light_use_cct = getSetting("useCCT", LIGHT_USE_CCT).toInt() == 1;
if (_light_use_cct && ((_light_channel.size() < 5) || !_light_use_white)) {
if (_light_use_cct && (((_light_channel.size() < 5) && (_light_channel.size() != 2)) || !_light_use_white)) {
_light_use_cct = false; _light_use_cct = false;
setSetting("useCCT", _light_use_cct); setSetting("useCCT", _light_use_cct);
} }


+ 124
- 87
code/espurna/mqtt.ino View File

@ -13,6 +13,7 @@ Copyright (C) 2016-2019 by Xose Pérez <xose dot perez at gmail dot com>
#include <ESP8266mDNS.h> #include <ESP8266mDNS.h>
#include <ArduinoJson.h> #include <ArduinoJson.h>
#include <vector> #include <vector>
#include <utility>
#include <Ticker.h> #include <Ticker.h>
#if MQTT_USE_ASYNC // Using AsyncMqttClient #if MQTT_USE_ASYNC // Using AsyncMqttClient
@ -46,10 +47,12 @@ String _mqtt_topic_json;
String _mqtt_setter; String _mqtt_setter;
String _mqtt_getter; String _mqtt_getter;
bool _mqtt_forward; bool _mqtt_forward;
char *_mqtt_user = 0;
char *_mqtt_pass = 0;
char *_mqtt_will;
char *_mqtt_clientid;
String _mqtt_user;
String _mqtt_pass;
String _mqtt_will;
String _mqtt_server;
uint16_t _mqtt_port;
String _mqtt_clientid;
std::vector<mqtt_callback_f> _mqtt_callbacks; std::vector<mqtt_callback_f> _mqtt_callbacks;
@ -82,41 +85,23 @@ void _mqttConnect() {
_mqtt_reconnect_delay = MQTT_RECONNECT_DELAY_MAX; _mqtt_reconnect_delay = MQTT_RECONNECT_DELAY_MAX;
} }
String h = getSetting("mqttServer", MQTT_SERVER);
#if MDNS_CLIENT_SUPPORT #if MDNS_CLIENT_SUPPORT
h = mdnsResolve(h);
_mqtt_server = mdnsResolve(_mqtt_server);
#endif #endif
char * host = strdup(h.c_str());
unsigned int port = getSetting("mqttPort", MQTT_PORT).toInt();
if (_mqtt_user) free(_mqtt_user);
if (_mqtt_pass) free(_mqtt_pass);
if (_mqtt_will) free(_mqtt_will);
if (_mqtt_clientid) free(_mqtt_clientid);
String user = getSetting("mqttUser", MQTT_USER);
_mqttPlaceholders(&user);
_mqtt_user = strdup(user.c_str());
_mqtt_pass = strdup(getSetting("mqttPassword", MQTT_PASS).c_str());
_mqtt_will = strdup(mqttTopic(MQTT_TOPIC_STATUS, false).c_str());
String clientid = getSetting("mqttClientID", getIdentifier());
_mqttPlaceholders(&clientid);
_mqtt_clientid = strdup(clientid.c_str());
DEBUG_MSG_P(PSTR("[MQTT] Connecting to broker at %s:%d\n"), host, port);
DEBUG_MSG_P(PSTR("[MQTT] Connecting to broker at %s:%u\n"), _mqtt_server.c_str(), _mqtt_port);
#if MQTT_USE_ASYNC #if MQTT_USE_ASYNC
_mqtt_connecting = true; _mqtt_connecting = true;
_mqtt.setServer(host, port);
_mqtt.setClientId(_mqtt_clientid);
_mqtt.setServer(_mqtt_server.c_str(), _mqtt_port);
_mqtt.setClientId(_mqtt_clientid.c_str());
_mqtt.setKeepAlive(_mqtt_keepalive); _mqtt.setKeepAlive(_mqtt_keepalive);
_mqtt.setCleanSession(false); _mqtt.setCleanSession(false);
_mqtt.setWill(_mqtt_will, _mqtt_qos, _mqtt_retain, "0");
if ((strlen(_mqtt_user) > 0) && (strlen(_mqtt_pass) > 0)) {
DEBUG_MSG_P(PSTR("[MQTT] Connecting as user %s\n"), _mqtt_user);
_mqtt.setCredentials(_mqtt_user, _mqtt_pass);
_mqtt.setWill(_mqtt_will.c_str(), _mqtt_qos, _mqtt_retain, "0");
if (_mqtt_user.length() && _mqtt_pass.length()) {
DEBUG_MSG_P(PSTR("[MQTT] Connecting as user %s\n"), _mqtt_user.c_str());
_mqtt.setCredentials(_mqtt_user.c_str(), _mqtt_pass.c_str());
} }
#if ASYNC_TCP_SSL_ENABLED #if ASYNC_TCP_SSL_ENABLED
@ -135,11 +120,11 @@ void _mqttConnect() {
#endif // ASYNC_TCP_SSL_ENABLED #endif // ASYNC_TCP_SSL_ENABLED
DEBUG_MSG_P(PSTR("[MQTT] Client ID: %s\n"), _mqtt_clientid);
DEBUG_MSG_P(PSTR("[MQTT] Client ID: %s\n"), _mqtt_clientid.c_str());
DEBUG_MSG_P(PSTR("[MQTT] QoS: %d\n"), _mqtt_qos); DEBUG_MSG_P(PSTR("[MQTT] QoS: %d\n"), _mqtt_qos);
DEBUG_MSG_P(PSTR("[MQTT] Retain flag: %d\n"), _mqtt_retain ? 1 : 0); DEBUG_MSG_P(PSTR("[MQTT] Retain flag: %d\n"), _mqtt_retain ? 1 : 0);
DEBUG_MSG_P(PSTR("[MQTT] Keepalive time: %ds\n"), _mqtt_keepalive); DEBUG_MSG_P(PSTR("[MQTT] Keepalive time: %ds\n"), _mqtt_keepalive);
DEBUG_MSG_P(PSTR("[MQTT] Will topic: %s\n"), _mqtt_will);
DEBUG_MSG_P(PSTR("[MQTT] Will topic: %s\n"), _mqtt_will.c_str());
_mqtt.connect(); _mqtt.connect();
@ -152,10 +137,10 @@ void _mqttConnect() {
bool secure = getSetting("mqttUseSSL", MQTT_SSL_ENABLED).toInt() == 1; bool secure = getSetting("mqttUseSSL", MQTT_SSL_ENABLED).toInt() == 1;
if (secure) { if (secure) {
DEBUG_MSG_P(PSTR("[MQTT] Using SSL\n")); DEBUG_MSG_P(PSTR("[MQTT] Using SSL\n"));
if (_mqtt_client_secure.connect(host, port)) {
if (_mqtt_client_secure.connect(_mqtt_server.c_str(), _mqtt_port)) {
char fp[60] = {0}; char fp[60] = {0};
if (sslFingerPrintChar(getSetting("mqttFP", MQTT_SSL_FINGERPRINT).c_str(), fp)) { if (sslFingerPrintChar(getSetting("mqttFP", MQTT_SSL_FINGERPRINT).c_str(), fp)) {
if (_mqtt_client_secure.verify(fp, host)) {
if (_mqtt_client_secure.verify(fp, _mqtt_server.c_str())) {
_mqtt.setClient(_mqtt_client_secure); _mqtt.setClient(_mqtt_client_secure);
} else { } else {
DEBUG_MSG_P(PSTR("[MQTT] Invalid fingerprint\n")); DEBUG_MSG_P(PSTR("[MQTT] Invalid fingerprint\n"));
@ -184,20 +169,20 @@ void _mqttConnect() {
if (response) { if (response) {
_mqtt.setServer(host, port);
_mqtt.setServer(_mqtt_server.c_str(), _mqtt_port);
if ((strlen(_mqtt_user) > 0) && (strlen(_mqtt_pass) > 0)) {
DEBUG_MSG_P(PSTR("[MQTT] Connecting as user %s\n"), _mqtt_user);
response = _mqtt.connect(_mqtt_clientid, _mqtt_user, _mqtt_pass, _mqtt_will, _mqtt_qos, _mqtt_retain, "0");
if (_mqtt_user.length() && _mqtt_pass.length()) {
DEBUG_MSG_P(PSTR("[MQTT] Connecting as user %s\n"), _mqtt_user.c_str());
response = _mqtt.connect(_mqtt_clientid.c_str(), _mqtt_user.c_str(), _mqtt_pass.c_str(), _mqtt_will.c_str(), _mqtt_qos, _mqtt_retain, "0");
} else { } else {
response = _mqtt.connect(_mqtt_clientid, _mqtt_will, _mqtt_qos, _mqtt_retain, "0");
response = _mqtt.connect(_mqtt_clientid.c_str(), _mqtt_will.c_str(), _mqtt_qos, _mqtt_retain, "0");
} }
DEBUG_MSG_P(PSTR("[MQTT] Client ID: %s\n"), _mqtt_clientid);
DEBUG_MSG_P(PSTR("[MQTT] Client ID: %s\n"), _mqtt_clientid.c_str());
DEBUG_MSG_P(PSTR("[MQTT] QoS: %d\n"), _mqtt_qos); DEBUG_MSG_P(PSTR("[MQTT] QoS: %d\n"), _mqtt_qos);
DEBUG_MSG_P(PSTR("[MQTT] Retain flag: %d\n"), _mqtt_retain ? 1 : 0); DEBUG_MSG_P(PSTR("[MQTT] Retain flag: %d\n"), _mqtt_retain ? 1 : 0);
DEBUG_MSG_P(PSTR("[MQTT] Keepalive time: %ds\n"), _mqtt_keepalive); DEBUG_MSG_P(PSTR("[MQTT] Keepalive time: %ds\n"), _mqtt_keepalive);
DEBUG_MSG_P(PSTR("[MQTT] Will topic: %s\n"), _mqtt_will);
DEBUG_MSG_P(PSTR("[MQTT] Will topic: %s\n"), _mqtt_will.c_str());
} }
@ -210,50 +195,114 @@ void _mqttConnect() {
#endif // MQTT_USE_ASYNC #endif // MQTT_USE_ASYNC
free(host);
} }
void _mqttPlaceholders(String *text) {
text->replace("{hostname}", getSetting("hostname"));
text->replace("{magnitude}", "#");
void _mqttPlaceholders(String& text) {
text.replace("{hostname}", getSetting("hostname"));
text.replace("{magnitude}", "#");
String mac = WiFi.macAddress(); String mac = WiFi.macAddress();
mac.replace(":", ""); mac.replace(":", "");
text->replace("{mac}", mac);
text.replace("{mac}", mac);
} }
template<typename T>
void _mqttApplySetting(T& current, T& updated) {
if (current != updated) {
current = std::move(updated);
mqttDisconnect();
}
}
template<typename T>
void _mqttApplySetting(T& current, const T& updated) {
if (current != updated) {
current = updated;
mqttDisconnect();
}
}
template<typename T>
void _mqttApplyTopic(T& current, const char* magnitude) {
String updated = mqttTopic(magnitude, false);
if (current != updated) {
mqttFlush();
current = std::move(updated);
}
}
void _mqttConfigure() { void _mqttConfigure() {
// Get base topic
_mqtt_topic = getSetting("mqttTopic", MQTT_TOPIC);
if (_mqtt_topic.endsWith("/")) _mqtt_topic.remove(_mqtt_topic.length()-1);
// Enable only when server is set
{
String server = getSetting("mqttServer", MQTT_SERVER);
uint16_t port = getSetting("mqttPort", MQTT_PORT).toInt();
bool enabled = false;
if (server.length()) {
enabled = getSetting("mqttEnabled", MQTT_ENABLED).toInt() == 1;
}
_mqttApplySetting(_mqtt_server, server);
_mqttApplySetting(_mqtt_enabled, enabled);
_mqttApplySetting(_mqtt_port, port);
if (!enabled) return;
}
// Get base topic and apply placeholders
{
String topic = getSetting("mqttTopic", MQTT_TOPIC);
if (topic.endsWith("/")) topic.remove(topic.length()-1);
// Placeholders
_mqttPlaceholders(&_mqtt_topic);
if (_mqtt_topic.indexOf("#") == -1) _mqtt_topic = _mqtt_topic + "/#";
// Replace things inside curly braces (like {hostname}, {mac} etc.)
_mqttPlaceholders(topic);
// Getters and setters
_mqtt_setter = getSetting("mqttSetter", MQTT_SETTER);
_mqtt_getter = getSetting("mqttGetter", MQTT_GETTER);
_mqtt_forward = !_mqtt_getter.equals(_mqtt_setter) && RELAY_REPORT_STATUS;
if (topic.indexOf("#") == -1) topic.concat("/#");
_mqttApplySetting(_mqtt_topic, topic);
_mqttApplyTopic(_mqtt_will, MQTT_TOPIC_STATUS);
}
// Getter and setter
{
String setter = getSetting("mqttSetter", MQTT_SETTER);
String getter = getSetting("mqttGetter", MQTT_GETTER);
bool forward = !setter.equals(getter) && RELAY_REPORT_STATUS;
_mqttApplySetting(_mqtt_setter, setter);
_mqttApplySetting(_mqtt_getter, getter);
_mqttApplySetting(_mqtt_forward, forward);
}
// MQTT options // MQTT options
_mqtt_qos = getSetting("mqttQoS", MQTT_QOS).toInt();
_mqtt_retain = getSetting("mqttRetain", MQTT_RETAIN).toInt() == 1;
_mqtt_keepalive = getSetting("mqttKeep", MQTT_KEEPALIVE).toInt();
if (getSetting("mqttClientID").length() == 0) delSetting("mqttClientID");
// Enable
if (getSetting("mqttServer", MQTT_SERVER).length() == 0) {
mqttEnabled(false);
} else {
_mqtt_enabled = getSetting("mqttEnabled", MQTT_ENABLED).toInt() == 1;
{
String user = getSetting("mqttUser", MQTT_USER);
_mqttPlaceholders(user);
String pass = getSetting("mqttPassword", MQTT_PASS);
unsigned char qos = getSetting("mqttQoS", MQTT_QOS).toInt();
bool retain = getSetting("mqttRetain", MQTT_RETAIN).toInt() == 1;
unsigned long keepalive = getSetting("mqttKeep", MQTT_KEEPALIVE).toInt();
String id = getSetting("mqttClientID", getIdentifier());
_mqttPlaceholders(id);
_mqttApplySetting(_mqtt_user, user);
_mqttApplySetting(_mqtt_pass, pass);
_mqttApplySetting(_mqtt_qos, qos);
_mqttApplySetting(_mqtt_retain, retain);
_mqttApplySetting(_mqtt_keepalive, keepalive);
_mqttApplySetting(_mqtt_clientid, id);
}
// MQTT JSON
{
_mqttApplySetting(_mqtt_use_json, getSetting("mqttUseJson", MQTT_USE_JSON).toInt() == 1);
_mqttApplyTopic(_mqtt_topic_json, MQTT_TOPIC_JSON);
} }
_mqtt_use_json = (getSetting("mqttUseJson", MQTT_USE_JSON).toInt() == 1);
mqttQueueTopic(MQTT_TOPIC_JSON);
_mqtt_reconnect_delay = MQTT_RECONNECT_DELAY_MIN; _mqtt_reconnect_delay = MQTT_RECONNECT_DELAY_MIN;
@ -491,9 +540,6 @@ void mqttSend(const char * topic, const char * message, bool force, bool retain)
// Equeue message // Equeue message
if (useJson) { if (useJson) {
// Set default queue topic
mqttQueueTopic(MQTT_TOPIC_JSON);
// Enqueue new message // Enqueue new message
mqttEnqueue(topic, message); mqttEnqueue(topic, message);
@ -608,14 +654,6 @@ void mqttFlush() {
} }
void mqttQueueTopic(const char * topic) {
String t = mqttTopic(topic, false);
if (!t.equals(_mqtt_topic_json)) {
mqttFlush();
_mqtt_topic_json = t;
}
}
int8_t mqttEnqueue(const char * topic, const char * message, unsigned char parent) { int8_t mqttEnqueue(const char * topic, const char * message, unsigned char parent) {
// Queue is not meant to send message "offline" // Queue is not meant to send message "offline"
@ -709,7 +747,11 @@ void mqttRegister(mqtt_callback_f callback) {
void mqttSetBroker(IPAddress ip, unsigned int port) { void mqttSetBroker(IPAddress ip, unsigned int port) {
setSetting("mqttServer", ip.toString()); setSetting("mqttServer", ip.toString());
_mqtt_server = ip.toString();
setSetting("mqttPort", port); setSetting("mqttPort", port);
_mqtt_port = port;
mqttEnabled(MQTT_AUTOCONNECT); mqttEnabled(MQTT_AUTOCONNECT);
} }
@ -717,11 +759,6 @@ void mqttSetBrokerIfNone(IPAddress ip, unsigned int port) {
if (getSetting("mqttServer", MQTT_SERVER).length() == 0) mqttSetBroker(ip, port); if (getSetting("mqttServer", MQTT_SERVER).length() == 0) mqttSetBroker(ip, port);
} }
void mqttReset() {
_mqttConfigure();
mqttDisconnect();
}
// ----------------------------------------------------------------------------- // -----------------------------------------------------------------------------
// Initialization // Initialization
// ----------------------------------------------------------------------------- // -----------------------------------------------------------------------------


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


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


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


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


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


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


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


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


+ 0
- 12
code/espurna/ws.ino View File

@ -212,9 +212,6 @@ void _wsParse(AsyncWebSocketClient *client, uint8_t * payload, size_t length) {
String adminPass; String adminPass;
bool save = false; bool save = false;
#if MQTT_SUPPORT
bool changedMQTT = false;
#endif
for (auto kv: config) { for (auto kv: config) {
@ -263,9 +260,6 @@ void _wsParse(AsyncWebSocketClient *client, uint8_t * payload, size_t length) {
// Update flags if value has changed // Update flags if value has changed
if (changed) { if (changed) {
save = true; save = true;
#if MQTT_SUPPORT
if (key.startsWith("mqtt")) changedMQTT = true;
#endif
} }
} }
@ -276,12 +270,6 @@ void _wsParse(AsyncWebSocketClient *client, uint8_t * payload, size_t length) {
// Callbacks // Callbacks
espurnaReload(); espurnaReload();
// This should got to callback as well
// but first change management has to be in place
#if MQTT_SUPPORT
if (changedMQTT) mqttReset();
#endif
// Persist settings // Persist settings
saveSettings(); saveSettings();


+ 2
- 2
code/html/index.html View File

@ -508,7 +508,7 @@
<div class="pure-u-1 pure-u-lg-1-4"><input type="checkbox" name="useWhite" action="reload" tabindex="9" /></div> <div class="pure-u-1 pure-u-lg-1-4"><input type="checkbox" name="useWhite" action="reload" tabindex="9" /></div>
<div class="pure-u-0 pure-u-lg-1-2"></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-0 pure-u-lg-1-4"></div>
<div class="pure-u-1 pure-u-lg-3-4 hint">Use forth dimmable channel as (cold) white light calculated out of the RGB values.<br />Will only work if the device has at least 4 dimmable channels.<br />Enabling this will render useless the "Channel 4" slider in the status page.<br />Reload the page to update the web interface.</div>
<div class="pure-u-1 pure-u-lg-3-4 hint">For 2 channels warm white and cold white lights or color lights to use forth dimmable channel as (cold) white light calculated out of the RGB values.<br />Will only work if the device has at least 4 dimmable channels.<br />Enabling this will render useless the "Channel 4" slider in the status page.<br />Reload the page to update the web interface.</div>
</div> </div>
<div class="pure-g"> <div class="pure-g">
@ -516,7 +516,7 @@
<div class="pure-u-1 pure-u-lg-1-4"><input type="checkbox" name="useCCT" action="reload" tabindex="10" /></div> <div class="pure-u-1 pure-u-lg-1-4"><input type="checkbox" name="useCCT" action="reload" tabindex="10" /></div>
<div class="pure-u-0 pure-u-lg-1-2"></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-0 pure-u-lg-1-4"></div>
<div class="pure-u-1 pure-u-lg-3-4 hint">Use fifth dimmable channel as warm white light and the forth dimmable channel as cold white.<br />Will only work if the device has at least 5 dimmable channels and "white channel" above is also ON.<br />Enabling this will render useless the "Channel 5" slider in the status page.<br />Reload the page to update the web interface.</div>
<div class="pure-u-1 pure-u-lg-3-4 hint">Use a dimmable channel as warm white light and another dimmable channel as cold white light.<br />On devices with two dimmable channels the first use used for warm white light and the second for cold white light.<br />On color lights the fifth use used for warm white light and the fourth for cold white light.<br />Will only work if the device has exactly 2 dimmable channels or at least 5 dimmable channels and "white channel" above is also ON.<br />Enabling this will render useless the "Channel 5" slider in the status page.<br />Reload the page to update the web interface.</div>
</div> </div>
<div class="pure-g"> <div class="pure-g">


+ 4
- 0
code/platformio.ini View File

@ -14,12 +14,16 @@ data_dir = espurna/data
# arduino core 2.4.1 = platformIO 1.7.3 # arduino core 2.4.1 = platformIO 1.7.3
# arduino core 2.4.2 = platformIO 1.8.0 # arduino core 2.4.2 = platformIO 1.8.0
# arduino core 2.5.0 = platformIO 2.0.4 # arduino core 2.5.0 = platformIO 2.0.4
# arduino core 2.5.1 = platformIO 2.1.1
# arduino core 2.5.2 = platformIO 2.2.1
# ------------------------------------------------------------------------------ # ------------------------------------------------------------------------------
arduino_core_2_3_0 = espressif8266@1.5.0 arduino_core_2_3_0 = espressif8266@1.5.0
arduino_core_2_4_0 = espressif8266@1.6.0 arduino_core_2_4_0 = espressif8266@1.6.0
arduino_core_2_4_1 = espressif8266@1.7.3 arduino_core_2_4_1 = espressif8266@1.7.3
arduino_core_2_4_2 = espressif8266@1.8.0 arduino_core_2_4_2 = espressif8266@1.8.0
arduino_core_2_5_0 = espressif8266@2.0.4 arduino_core_2_5_0 = espressif8266@2.0.4
arduino_core_2_5_1 = espressif8266@2.1.1
arduino_core_2_5_2 = espressif8266@2.2.1
platform = ${common.arduino_core_2_3_0} platform = ${common.arduino_core_2_3_0}
platform_latest = ${common.arduino_core_2_4_2} platform_latest = ${common.arduino_core_2_4_2}


BIN
images/devices/generic-ag-l4-2.jpg View File

Before After
Width: 960  |  Height: 1280  |  Size: 221 KiB Width: 1280  |  Height: 1266  |  Size: 314 KiB

Loading…
Cancel
Save