Browse Source

Issues #50 and #54. Fix domoticz sensor message format. Added energy calculation

fastled
Xose Pérez 7 years ago
parent
commit
24d0aa0b48
9 changed files with 112 additions and 11 deletions
  1. +7
    -0
      code/espurna/config/general.h
  2. +1
    -0
      code/espurna/config/prototypes.h
  3. +6
    -0
      code/espurna/config/sensors.h
  4. +16
    -2
      code/espurna/dht.ino
  5. +7
    -3
      code/espurna/domoticz.ino
  6. +1
    -1
      code/espurna/ds18b20.ino
  7. +36
    -1
      code/espurna/emon.ino
  8. +35
    -1
      code/espurna/pow.ino
  9. +3
    -3
      code/espurna/relay.ino

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

@ -7,6 +7,13 @@
#define BUFFER_SIZE 1024 #define BUFFER_SIZE 1024
#define HEARTBEAT_INTERVAL 300000 #define HEARTBEAT_INTERVAL 300000
//--------------------------------------------------------------------------------
// EEPROM
//--------------------------------------------------------------------------------
#define EEPROM_RELAY_STATUS 0
#define EEPROM_POWER_COUNT 1
//-------------------------------------------------------------------------------- //--------------------------------------------------------------------------------
// RELAY // RELAY
//-------------------------------------------------------------------------------- //--------------------------------------------------------------------------------


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

@ -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> bool setSetting(const String& key, T value);
template<typename T> String getSetting(const String& key, T defaultValue); 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 value);
template<typename T> void domoticzSend(const char * key, T nvalue, const char * svalue);

+ 6
- 0
code/espurna/config/sensors.h View File

@ -20,6 +20,11 @@
#define DHT_TEMPERATURE_TOPIC "/temperature" #define DHT_TEMPERATURE_TOPIC "/temperature"
#define DHT_HUMIDITY_TOPIC "/humidity" #define DHT_HUMIDITY_TOPIC "/humidity"
#define HUMIDITY_NORMAL 0
#define HUMIDITY_COMFORTABLE 1
#define HUMIDITY_DRY 2
#define HUMIDITY_WET 3
//-------------------------------------------------------------------------------- //--------------------------------------------------------------------------------
// DS18B20 temperature sensor // DS18B20 temperature sensor
// Enable support by passing ENABLE_DS18B20=1 build flag // Enable support by passing ENABLE_DS18B20=1 build flag
@ -46,6 +51,7 @@
#define EMON_MAINS_VOLTAGE 230 #define EMON_MAINS_VOLTAGE 230
#define EMON_CURRENT_RATIO 180 #define EMON_CURRENT_RATIO 180
#define EMON_POWER_TOPIC "/power" #define EMON_POWER_TOPIC "/power"
#define EMON_ENERGY_TOPIC "/energy"
//-------------------------------------------------------------------------------- //--------------------------------------------------------------------------------
// HLW8012 power sensor (Sonoff POW) // HLW8012 power sensor (Sonoff POW)


+ 16
- 2
code/espurna/dht.ino View File

@ -73,8 +73,22 @@ void dhtLoop() {
// Send to Domoticz // Send to Domoticz
#if ENABLE_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 #endif
// Update websocket clients // Update websocket clients


+ 7
- 3
code/espurna/domoticz.ino View File

@ -8,13 +8,17 @@ Copyright (C) 2016-2017 by Xose Pérez <xose dot perez at gmail dot com>
#if ENABLE_DOMOTICZ #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(); unsigned int idx = getSetting(key).toInt();
if (idx > 0) { 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); mqttSendRaw(getSetting("dczTopicIn", DOMOTICZ_IN_TOPIC).c_str(), payload);
} }
} }
template<typename T> void domoticzSend(const char * key, T nvalue) {
domoticzSend(key, nvalue, "");
}
#endif #endif

+ 1
- 1
code/espurna/ds18b20.ino View File

@ -62,7 +62,7 @@ void dsLoop() {
// Send to Domoticz // Send to Domoticz
#if ENABLE_DOMOTICZ #if ENABLE_DOMOTICZ
domoticzSend("dczTmpIdx", temperature);
domoticzSend("dczTmpIdx", 0, temperature);
#endif #endif
// Update websocket clients // Update websocket clients


+ 36
- 1
code/espurna/emon.ino View File

@ -9,10 +9,12 @@ Copyright (C) 2016-2017 by Xose Pérez <xose dot perez at gmail dot com>
#if ENABLE_EMON #if ENABLE_EMON
#include <EmonLiteESP.h> #include <EmonLiteESP.h>
#include <EEPROM.h>
EmonLiteESP emon; EmonLiteESP emon;
double _current = 0; double _current = 0;
unsigned int _power = 0; unsigned int _power = 0;
double _energy = 0;
// ----------------------------------------------------------------------------- // -----------------------------------------------------------------------------
// EMON // EMON
@ -26,6 +28,10 @@ unsigned int getPower() {
return _power; return _power;
} }
double getEnergy() {
return _energy;
}
double getCurrent() { double getCurrent() {
return _current; return _current;
} }
@ -34,6 +40,20 @@ unsigned int currentCallback() {
return analogRead(EMON_CURRENT_PIN); 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() { void powerMonitorSetup() {
// backwards compatibility // backwards compatibility
@ -56,6 +76,11 @@ void powerMonitorSetup() {
apiRegister("/api/power", "power", [](char * buffer, size_t len) { apiRegister("/api/power", "power", [](char * buffer, size_t len) {
snprintf(buffer, len, "%d", _power); 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) { if (measurements == EMON_MEASUREMENTS) {
_power = (int) ((sum - max - min) * mainsVoltage / (measurements - 2)); _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; sum = 0;
measurements = 0; measurements = 0;
char power[6]; char power[6];
snprintf(power, 6, "%d", _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("emonPowerTopic", EMON_POWER_TOPIC).c_str(), power);
mqttSend(getSetting("emonEnergyTopic", EMON_ENERGY_TOPIC).c_str(), energy);
#if ENABLE_DOMOTICZ #if ENABLE_DOMOTICZ
domoticzSend("dczPowIdx", power);
{
char buffer[20];
snprintf(buffer, 20, "%s;%s", power, energy);
domoticzSend("dczPowIdx", 0, buffer);
}
#endif #endif


+ 35
- 1
code/espurna/pow.ino View File

@ -12,9 +12,11 @@ Copyright (C) 2016-2017 by Xose Pérez <xose dot perez at gmail dot com>
#include <HLW8012.h> #include <HLW8012.h>
#include <Hash.h> #include <Hash.h>
#include <ArduinoJson.h> #include <ArduinoJson.h>
#include <EEPROM.h>
HLW8012 hlw8012; HLW8012 hlw8012;
bool _powEnabled = false; bool _powEnabled = false;
double _energy = 0;
// ----------------------------------------------------------------------------- // -----------------------------------------------------------------------------
// POW // POW
@ -117,8 +119,26 @@ unsigned int getPowerFactor() {
return (int) (100 * hlw8012.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() { void powSetup() {
// Initialize HLW8012 // Initialize HLW8012
@ -143,10 +163,16 @@ void powSetup() {
// Retrieve calibration values // Retrieve calibration values
powRetrieveCalibration(); powRetrieveCalibration();
// Recover energy reading
retrieveEnergy();
// API definitions // API definitions
apiRegister("/api/power", "power", [](char * buffer, size_t len) { apiRegister("/api/power", "power", [](char * buffer, size_t len) {
snprintf(buffer, len, "%d", getActivePower()); 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) { apiRegister("/api/current", "current", [](char * buffer, size_t len) {
dtostrf(getCurrent(), len-1, 2, buffer); dtostrf(getCurrent(), len-1, 2, buffer);
}); });
@ -216,8 +242,12 @@ void powLoop() {
reactive = (apparent > power) ? sqrt(apparent * apparent - power * power) : 0; reactive = (apparent > power) ? sqrt(apparent * apparent - power * power) : 0;
factor = (apparent > 0) ? 100 * power / apparent : 100; factor = (apparent > 0) ? 100 * power / apparent : 100;
if (factor > 100) factor = 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("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("powCurrentTopic", POW_CURRENT_TOPIC).c_str(), String(current).c_str());
mqttSend(getSetting("powVoltageTopic", POW_VOLTAGE_TOPIC).c_str(), String(voltage).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()); 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()); mqttSend(getSetting("powPFactorTopic", POW_PFACTOR_TOPIC).c_str(), String(factor).c_str());
#if ENABLE_DOMOTICZ #if ENABLE_DOMOTICZ
domoticzSend("dczPowIdx", power);
{
char buffer[20];
snprintf(buffer, 20, "%d;%ld", power, (unsigned long) _energy);
domoticzSend("dczPowIdx", 0, buffer);
}
#endif #endif
power_sum = current_sum = voltage_sum = 0; power_sum = current_sum = voltage_sum = 0;


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

@ -208,20 +208,20 @@ void relaySave() {
if (relayStatus(i)) mask += bit; if (relayStatus(i)) mask += bit;
bit += bit; bit += bit;
} }
EEPROM.write(0, mask);
EEPROM.write(EEPROM_RELAY_STATUS, mask);
EEPROM.commit(); EEPROM.commit();
} }
void relayRetrieve(bool invert) { void relayRetrieve(bool invert) {
recursive = true; recursive = true;
unsigned char bit = 1; 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++) { for (unsigned int i=0; i < _relays.size(); i++) {
relayStatus(i, ((mask & bit) == bit)); relayStatus(i, ((mask & bit) == bit));
bit += bit; bit += bit;
} }
if (invert) { if (invert) {
EEPROM.write(0, mask);
EEPROM.write(EEPROM_RELAY_STATUS, mask);
EEPROM.commit(); EEPROM.commit();
} }
recursive = false; recursive = false;


Loading…
Cancel
Save