mirror of
https://github.com/xoseperez/espurna.git
synced 2026-03-09 17:57:08 +01:00
Merge branch 'dev' into toggle-switch
This commit is contained in:
2
code/build-fs
Executable file
2
code/build-fs
Executable file
@@ -0,0 +1,2 @@
|
||||
#!/bin/bash
|
||||
node node_modules/gulp/bin/gulp.js
|
||||
@@ -28,6 +28,7 @@
|
||||
//#define WIFI_RELAY_NC
|
||||
//#define WIFI_RELAY_NO
|
||||
//#define ESPURNA
|
||||
//#define MQTT_RELAY
|
||||
|
||||
//--------------------------------------------------------------------------------
|
||||
// Features (values below are non-default values)
|
||||
|
||||
@@ -7,6 +7,13 @@
|
||||
#define BUFFER_SIZE 1024
|
||||
#define HEARTBEAT_INTERVAL 300000
|
||||
|
||||
//--------------------------------------------------------------------------------
|
||||
// EEPROM
|
||||
//--------------------------------------------------------------------------------
|
||||
|
||||
#define EEPROM_RELAY_STATUS 0
|
||||
#define EEPROM_POWER_COUNT 1
|
||||
|
||||
//--------------------------------------------------------------------------------
|
||||
// RELAY
|
||||
//--------------------------------------------------------------------------------
|
||||
|
||||
@@ -256,6 +256,21 @@
|
||||
#define LED1_PIN 13
|
||||
#define LED1_PIN_INVERSE 0
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
// WiFi MQTT Relay / Thermostat
|
||||
// -----------------------------------------------------------------------------
|
||||
|
||||
#elif defined(MQTT_RELAY)
|
||||
|
||||
#define MANUFACTURER "OPENENERGYMONITOR"
|
||||
#define DEVICE "MQTT_RELAY"
|
||||
#define BUTTON1_PIN 0
|
||||
#define BUTTON1_RELAY 1
|
||||
#define RELAY1_PIN 12
|
||||
#define RELAY1_PIN_INVERSE 0
|
||||
#define LED1_PIN 16
|
||||
#define LED1_PIN_INVERSE 0
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
// Unknown hardware
|
||||
// -----------------------------------------------------------------------------
|
||||
|
||||
@@ -12,3 +12,4 @@ void mqttRegister(void (*callback)(unsigned int, const char *, const char *));
|
||||
template<typename T> bool setSetting(const String& key, T value);
|
||||
template<typename T> String getSetting(const String& key, T defaultValue);
|
||||
template<typename T> void domoticzSend(const char * key, T value);
|
||||
template<typename T> void domoticzSend(const char * key, T nvalue, const char * svalue);
|
||||
|
||||
@@ -20,6 +20,11 @@
|
||||
#define DHT_TEMPERATURE_TOPIC "/temperature"
|
||||
#define DHT_HUMIDITY_TOPIC "/humidity"
|
||||
|
||||
#define HUMIDITY_NORMAL 0
|
||||
#define HUMIDITY_COMFORTABLE 1
|
||||
#define HUMIDITY_DRY 2
|
||||
#define HUMIDITY_WET 3
|
||||
|
||||
//--------------------------------------------------------------------------------
|
||||
// DS18B20 temperature sensor
|
||||
// Enable support by passing ENABLE_DS18B20=1 build flag
|
||||
@@ -46,6 +51,7 @@
|
||||
#define EMON_MAINS_VOLTAGE 230
|
||||
#define EMON_CURRENT_RATIO 180
|
||||
#define EMON_POWER_TOPIC "/power"
|
||||
#define EMON_ENERGY_TOPIC "/energy"
|
||||
|
||||
//--------------------------------------------------------------------------------
|
||||
// HLW8012 power sensor (Sonoff POW)
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
#define APP_NAME "ESPurna"
|
||||
#define APP_VERSION "1.5.0"
|
||||
#define APP_VERSION "1.5.3"
|
||||
#define APP_AUTHOR "xose.perez@gmail.com"
|
||||
#define APP_WEBSITE "http://tinkerman.cat"
|
||||
|
||||
@@ -73,8 +73,22 @@ void dhtLoop() {
|
||||
|
||||
// Send to Domoticz
|
||||
#if ENABLE_DOMOTICZ
|
||||
domoticzSend("dczTmpIdx", temperature);
|
||||
domoticzSend("dczHumIdx", humidity);
|
||||
{
|
||||
domoticzSend("dczTmpIdx", 0, temperature);
|
||||
int status;
|
||||
if (h > 70) {
|
||||
status = HUMIDITY_WET;
|
||||
} else if (h > 45) {
|
||||
status = HUMIDITY_COMFORTABLE;
|
||||
} else if (h > 30) {
|
||||
status = HUMIDITY_NORMAL;
|
||||
} else {
|
||||
status = HUMIDITY_DRY;
|
||||
}
|
||||
char buffer[2];
|
||||
sprintf(buffer, "%d", status);
|
||||
domoticzSend("dczHumIdx", humidity, buffer);
|
||||
}
|
||||
#endif
|
||||
|
||||
// Update websocket clients
|
||||
|
||||
@@ -8,13 +8,17 @@ Copyright (C) 2016-2017 by Xose Pérez <xose dot perez at gmail dot com>
|
||||
|
||||
#if ENABLE_DOMOTICZ
|
||||
|
||||
template<typename T> void domoticzSend(const char * key, T value) {
|
||||
template<typename T> void domoticzSend(const char * key, T nvalue, const char * svalue) {
|
||||
unsigned int idx = getSetting(key).toInt();
|
||||
if (idx > 0) {
|
||||
char payload[45];
|
||||
sprintf(payload, "{\"idx\": %d, \"nvalue\": %s, \"svalue\": \"\"}", idx, String(value).c_str());
|
||||
char payload[128];
|
||||
snprintf(payload, 128, "{\"idx\": %d, \"nvalue\": %s, \"svalue\": \"%s\"}", idx, String(nvalue).c_str(), svalue);
|
||||
mqttSendRaw(getSetting("dczTopicIn", DOMOTICZ_IN_TOPIC).c_str(), payload);
|
||||
}
|
||||
}
|
||||
|
||||
template<typename T> void domoticzSend(const char * key, T nvalue) {
|
||||
domoticzSend(key, nvalue, "");
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
@@ -62,7 +62,7 @@ void dsLoop() {
|
||||
|
||||
// Send to Domoticz
|
||||
#if ENABLE_DOMOTICZ
|
||||
domoticzSend("dczTmpIdx", temperature);
|
||||
domoticzSend("dczTmpIdx", 0, temperature);
|
||||
#endif
|
||||
|
||||
// Update websocket clients
|
||||
|
||||
@@ -9,10 +9,12 @@ Copyright (C) 2016-2017 by Xose Pérez <xose dot perez at gmail dot com>
|
||||
#if ENABLE_EMON
|
||||
|
||||
#include <EmonLiteESP.h>
|
||||
#include <EEPROM.h>
|
||||
|
||||
EmonLiteESP emon;
|
||||
double _current = 0;
|
||||
unsigned int _power = 0;
|
||||
double _energy = 0;
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
// EMON
|
||||
@@ -26,6 +28,10 @@ unsigned int getPower() {
|
||||
return _power;
|
||||
}
|
||||
|
||||
double getEnergy() {
|
||||
return _energy;
|
||||
}
|
||||
|
||||
double getCurrent() {
|
||||
return _current;
|
||||
}
|
||||
@@ -34,6 +40,20 @@ unsigned int currentCallback() {
|
||||
return analogRead(EMON_CURRENT_PIN);
|
||||
}
|
||||
|
||||
void retrieveEnergy() {
|
||||
unsigned long energy = EEPROM.read(EEPROM_POWER_COUNT + 1);
|
||||
energy = (energy << 8) + EEPROM.read(EEPROM_POWER_COUNT);
|
||||
if (energy == 0xFFFF) energy = 0;
|
||||
_energy = energy;
|
||||
}
|
||||
|
||||
void saveEnergy() {
|
||||
unsigned int energy = (int) _energy;
|
||||
EEPROM.write(EEPROM_POWER_COUNT, energy & 0xFF);
|
||||
EEPROM.write(EEPROM_POWER_COUNT + 1, (energy >> 8) & 0xFF);
|
||||
EEPROM.commit();
|
||||
}
|
||||
|
||||
void powerMonitorSetup() {
|
||||
|
||||
// backwards compatibility
|
||||
@@ -56,6 +76,11 @@ void powerMonitorSetup() {
|
||||
apiRegister("/api/power", "power", [](char * buffer, size_t len) {
|
||||
snprintf(buffer, len, "%d", _power);
|
||||
});
|
||||
apiRegister("/api/energy", "energy", [](char * buffer, size_t len) {
|
||||
snprintf(buffer, len, "%ld", (unsigned long) _energy);
|
||||
});
|
||||
|
||||
retrieveEnergy();
|
||||
|
||||
}
|
||||
|
||||
@@ -108,14 +133,24 @@ void powerMonitorLoop() {
|
||||
if (measurements == EMON_MEASUREMENTS) {
|
||||
|
||||
_power = (int) ((sum - max - min) * mainsVoltage / (measurements - 2));
|
||||
double window = (double) EMON_INTERVAL * EMON_MEASUREMENTS / 1000.0 / 3600.0;
|
||||
_energy += _power * window;
|
||||
saveEnergy();
|
||||
sum = 0;
|
||||
measurements = 0;
|
||||
|
||||
char power[6];
|
||||
snprintf(power, "%d", 6, _power);
|
||||
snprintf(power, 6, "%d", _power);
|
||||
char energy[8];
|
||||
snprintf(energy, 6, "%ld", (unsigned long) _energy);
|
||||
mqttSend(getSetting("emonPowerTopic", EMON_POWER_TOPIC).c_str(), power);
|
||||
mqttSend(getSetting("emonEnergyTopic", EMON_ENERGY_TOPIC).c_str(), energy);
|
||||
#if ENABLE_DOMOTICZ
|
||||
domoticzSend("dczPowIdx", power);
|
||||
{
|
||||
char buffer[20];
|
||||
snprintf(buffer, 20, "%s;%s", power, energy);
|
||||
domoticzSend("dczPowIdx", 0, buffer);
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
@@ -14,7 +14,7 @@ Copyright (C) 2016-2017 by Xose Pérez <xose dot perez at gmail dot com>
|
||||
// NTP
|
||||
// -----------------------------------------------------------------------------
|
||||
|
||||
void ntpConnect(WiFiEventStationModeGotIP ipInfo) {
|
||||
void ntpConnect() {
|
||||
NTP.begin(NTP_SERVER, NTP_TIME_OFFSET, NTP_DAY_LIGHT);
|
||||
NTP.setInterval(NTP_UPDATE_INTERVAL);
|
||||
}
|
||||
@@ -33,9 +33,6 @@ void ntpSetup() {
|
||||
}
|
||||
});
|
||||
|
||||
static WiFiEventHandler e;
|
||||
e = WiFi.onStationModeGotIP(ntpConnect);
|
||||
|
||||
}
|
||||
|
||||
void ntpLoop() {
|
||||
|
||||
@@ -12,9 +12,11 @@ Copyright (C) 2016-2017 by Xose Pérez <xose dot perez at gmail dot com>
|
||||
#include <HLW8012.h>
|
||||
#include <Hash.h>
|
||||
#include <ArduinoJson.h>
|
||||
#include <EEPROM.h>
|
||||
|
||||
HLW8012 hlw8012;
|
||||
bool _powEnabled = false;
|
||||
double _energy = 0;
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
// POW
|
||||
@@ -117,8 +119,26 @@ unsigned int getPowerFactor() {
|
||||
return (int) (100 * hlw8012.getPowerFactor());
|
||||
}
|
||||
|
||||
double getEnergy() {
|
||||
return _energy;
|
||||
}
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
|
||||
void retrieveEnergy() {
|
||||
unsigned long energy = EEPROM.read(EEPROM_POWER_COUNT + 1);
|
||||
energy = (energy << 8) + EEPROM.read(EEPROM_POWER_COUNT);
|
||||
if (energy == 0xFFFF) energy = 0;
|
||||
_energy = energy;
|
||||
}
|
||||
|
||||
void saveEnergy() {
|
||||
unsigned int energy = (int) _energy;
|
||||
EEPROM.write(EEPROM_POWER_COUNT, energy & 0xFF);
|
||||
EEPROM.write(EEPROM_POWER_COUNT + 1, (energy >> 8) & 0xFF);
|
||||
EEPROM.commit();
|
||||
}
|
||||
|
||||
void powSetup() {
|
||||
|
||||
// Initialize HLW8012
|
||||
@@ -143,10 +163,16 @@ void powSetup() {
|
||||
// Retrieve calibration values
|
||||
powRetrieveCalibration();
|
||||
|
||||
// Recover energy reading
|
||||
retrieveEnergy();
|
||||
|
||||
// API definitions
|
||||
apiRegister("/api/power", "power", [](char * buffer, size_t len) {
|
||||
snprintf(buffer, len, "%d", getActivePower());
|
||||
});
|
||||
apiRegister("/api/energy", "energy", [](char * buffer, size_t len) {
|
||||
snprintf(buffer, len, "%ld", (unsigned long) _energy);
|
||||
});
|
||||
apiRegister("/api/current", "current", [](char * buffer, size_t len) {
|
||||
dtostrf(getCurrent(), len-1, 2, buffer);
|
||||
});
|
||||
@@ -216,8 +242,12 @@ void powLoop() {
|
||||
reactive = (apparent > power) ? sqrt(apparent * apparent - power * power) : 0;
|
||||
factor = (apparent > 0) ? 100 * power / apparent : 100;
|
||||
if (factor > 100) factor = 100;
|
||||
unsigned long window = (double) POW_REPORT_EVERY * POW_UPDATE_INTERVAL / 1000.0 / 3600.0;
|
||||
_energy += power * window;
|
||||
saveEnergy();
|
||||
|
||||
mqttSend(getSetting("powPowerTopic", POW_POWER_TOPIC).c_str(), String(power).c_str());
|
||||
mqttSend(getSetting("powEnergyTopic", POW_ENERGY_TOPIC).c_str(), String(_energy).c_str());
|
||||
mqttSend(getSetting("powCurrentTopic", POW_CURRENT_TOPIC).c_str(), String(current).c_str());
|
||||
mqttSend(getSetting("powVoltageTopic", POW_VOLTAGE_TOPIC).c_str(), String(voltage).c_str());
|
||||
mqttSend(getSetting("powAPowerTopic", POW_APOWER_TOPIC).c_str(), String(apparent).c_str());
|
||||
@@ -225,7 +255,11 @@ void powLoop() {
|
||||
mqttSend(getSetting("powPFactorTopic", POW_PFACTOR_TOPIC).c_str(), String(factor).c_str());
|
||||
|
||||
#if ENABLE_DOMOTICZ
|
||||
domoticzSend("dczPowIdx", power);
|
||||
{
|
||||
char buffer[20];
|
||||
snprintf(buffer, 20, "%d;%ld", power, (unsigned long) _energy);
|
||||
domoticzSend("dczPowIdx", 0, buffer);
|
||||
}
|
||||
#endif
|
||||
|
||||
power_sum = current_sum = voltage_sum = 0;
|
||||
|
||||
@@ -208,20 +208,21 @@ void relaySave() {
|
||||
if (relayStatus(i)) mask += bit;
|
||||
bit += bit;
|
||||
}
|
||||
EEPROM.write(0, mask);
|
||||
EEPROM.write(EEPROM_RELAY_STATUS, mask);
|
||||
EEPROM.commit();
|
||||
}
|
||||
|
||||
void relayRetrieve(bool invert) {
|
||||
recursive = true;
|
||||
unsigned char bit = 1;
|
||||
unsigned char mask = invert ? ~EEPROM.read(0) : EEPROM.read(0);
|
||||
unsigned char mask = invert ? ~EEPROM.read(EEPROM_RELAY_STATUS) : EEPROM.read(EEPROM_RELAY_STATUS);
|
||||
for (unsigned int i=0; i < _relays.size(); i++) {
|
||||
relayStatus(i, ((mask & bit) == bit));
|
||||
bit += bit;
|
||||
}
|
||||
if (invert) {
|
||||
relaySave();
|
||||
EEPROM.write(EEPROM_RELAY_STATUS, mask);
|
||||
EEPROM.commit();
|
||||
}
|
||||
recursive = false;
|
||||
}
|
||||
@@ -385,6 +386,7 @@ void relayMQTTCallback(unsigned int type, const char * topic, const char * paylo
|
||||
if (type == MQTT_MESSAGE_EVENT) {
|
||||
|
||||
// Match topic
|
||||
if (strncmp(topic, "domoticz", 8) == 0) return;
|
||||
String t = String(topic + mqttTopicRootLength());
|
||||
if (!t.startsWith(MQTT_RELAY_TOPIC)) return;
|
||||
if (!t.endsWith(mqttSetter)) return;
|
||||
|
||||
@@ -168,6 +168,11 @@ void wifiSetup() {
|
||||
dnsServer.stop();
|
||||
}
|
||||
|
||||
// NTP connection reset
|
||||
if (code == MESSAGE_CONNECTED) {
|
||||
ntpConnect();
|
||||
}
|
||||
|
||||
// Manage POW
|
||||
#if ENABLE_POW
|
||||
if (code == MESSAGE_CONNECTED) {
|
||||
|
||||
@@ -391,19 +391,19 @@
|
||||
<input class="pure-u-1 pure-u-md-3-4" name="dczTopicOut" type="text" tabindex="32" placeholder="domoticz/out" />
|
||||
</div>
|
||||
|
||||
<div class="pure-g modude module-dht module-ds">
|
||||
<div class="pure-g module module-dht module-ds">
|
||||
<label class="pure-u-1 pure-u-sm-1-4" for="dczTmpIdx">Temperature IDX</label>
|
||||
<div class="pure-u-1 pure-u-sm-1-8"><input class="pure-u-sm-23-24" name="dczTmpIdx" type="number" min="0" tabindex="33" data="0" /></div>
|
||||
<div class="pure-u-1 pure-u-sm-5-8 hint center">Set to 0 to disable notifications.</div>
|
||||
</div>
|
||||
|
||||
<div class="pure-g modude module-dht">
|
||||
<div class="pure-g module module-dht">
|
||||
<label class="pure-u-1 pure-u-sm-1-4" for="dczHumIdx">Humidity IDX</label>
|
||||
<div class="pure-u-1 pure-u-sm-1-8"><input class="pure-u-sm-23-24" name="dczHumIdx" type="number" min="0" tabindex="34" data="0" /></div>
|
||||
<div class="pure-u-1 pure-u-sm-5-8 hint center">Set to 0 to disable notifications.</div>
|
||||
</div>
|
||||
|
||||
<div class="pure-g modude module-pow module-emon">
|
||||
<div class="pure-g module module-pow module-emon">
|
||||
<label class="pure-u-1 pure-u-sm-1-4" for="dczPowIdx">Power IDX</label>
|
||||
<div class="pure-u-1 pure-u-sm-1-8"><input class="pure-u-sm-23-24" name="dczPowIdx" type="number" min="0" tabindex="35" data="0" /></div>
|
||||
<div class="pure-u-1 pure-u-sm-5-8 hint center">Set to 0 to disable notifications.</div>
|
||||
|
||||
@@ -6,6 +6,6 @@ from SCons.Script import DefaultEnvironment
|
||||
env = DefaultEnvironment()
|
||||
|
||||
def before_build_spiffs(source, target, env):
|
||||
env.Execute("gulp")
|
||||
env.Execute("node node_modules/gulp/bin/gulp.js")
|
||||
|
||||
env.AddPreAction(".pioenvs/%s/spiffs.bin" % env['PIOENV'], before_build_spiffs)
|
||||
|
||||
@@ -284,3 +284,24 @@ build_flags = -g -DDEBUG_PORT=Serial -DWIFI_RELAY_NC
|
||||
upload_speed = 115200
|
||||
upload_port = "192.168.4.1"
|
||||
upload_flags = --auth=fibonacci --port 8266
|
||||
|
||||
[env:mqtt-relay-debug]
|
||||
platform = espressif8266
|
||||
framework = arduino
|
||||
board = esp_wroom_02
|
||||
lib_deps = ${common.lib_deps}
|
||||
lib_ignore = ${common.lib_ignore}
|
||||
extra_script = pio_hooks.py
|
||||
build_flags = -g -DDEBUG_PORT=Serial -DMQTT_RELAY -DENABLE_DS18B20=1
|
||||
|
||||
[env:mqtt-relay-debug-ota]
|
||||
platform = espressif8266
|
||||
framework = arduino
|
||||
board = esp_wroom_02
|
||||
lib_deps = ${common.lib_deps}
|
||||
lib_ignore = ${common.lib_ignore}
|
||||
extra_script = pio_hooks.py
|
||||
build_flags = -g -DDEBUG_PORT=Serial -DMQTT_RELAY -DENABLE_DS18B20=1
|
||||
upload_speed = 115200
|
||||
upload_port = "192.168.4.1"
|
||||
upload_flags = --auth=fibonacci --port 8266
|
||||
|
||||
Reference in New Issue
Block a user