Browse Source

Pass safe buffer to api callbacks

fastled
Xose Pérez 7 years ago
parent
commit
bbac070c09
8 changed files with 84 additions and 62 deletions
  1. +1
    -1
      code/espurna/config/general.h
  2. +1
    -1
      code/espurna/config/prototypes.h
  3. +26
    -17
      code/espurna/dht.ino
  4. +13
    -9
      code/espurna/ds18b20.ino
  5. +27
    -20
      code/espurna/emon.ino
  6. +6
    -9
      code/espurna/pow.ino
  7. +2
    -2
      code/espurna/relay.ino
  8. +8
    -3
      code/espurna/web.ino

+ 1
- 1
code/espurna/config/general.h View File

@ -81,7 +81,7 @@
#define MQTT_MESSAGE_EVENT 2 #define MQTT_MESSAGE_EVENT 2
// Custom get and set postfixes // Custom get and set postfixes
// Use something like "/status" or "/set", with trailing slash
// Use something like "/status" or "/set", with leading slash
#define MQTT_USE_GETTER "" #define MQTT_USE_GETTER ""
#define MQTT_USE_SETTER "" #define MQTT_USE_SETTER ""


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

@ -5,7 +5,7 @@
#include <AsyncMqttClient.h> #include <AsyncMqttClient.h>
#include <functional> #include <functional>
typedef std::function<char *(void)> apiGetCallbackFunction;
typedef std::function<void(char *, size_t)> apiGetCallbackFunction;
typedef std::function<void(const char *)> apiPutCallbackFunction; typedef std::function<void(const char *)> apiPutCallbackFunction;
void apiRegister(const char * url, const char * key, apiGetCallbackFunction getFn, apiPutCallbackFunction putFn = NULL); void apiRegister(const char * url, const char * key, apiGetCallbackFunction getFn, apiPutCallbackFunction putFn = NULL);
void mqttRegister(void (*callback)(unsigned int, const char *, const char *)); void mqttRegister(void (*callback)(unsigned int, const char *, const char *));


+ 26
- 17
code/espurna/dht.ino View File

@ -13,25 +13,29 @@ Copyright (C) 2016-2017 by Xose Pérez <xose dot perez at gmail dot com>
DHT dht(DHT_PIN, DHT_TYPE, DHT_TIMING); DHT dht(DHT_PIN, DHT_TYPE, DHT_TIMING);
char dhtTemperature[6];
char dhtHumidity[6];
double _dhtTemperature = 0;
unsigned int _dhtHumidity = 0;
// ----------------------------------------------------------------------------- // -----------------------------------------------------------------------------
// Values // Values
// ----------------------------------------------------------------------------- // -----------------------------------------------------------------------------
char * getDHTTemperature() {
return dhtTemperature;
double getDHTTemperature() {
return _dhtTemperature;
} }
char * getDHTHumidity() {
return dhtHumidity;
unsigned int getDHTHumidity() {
return _dhtHumidity;
} }
void dhtSetup() { void dhtSetup() {
dht.begin(); dht.begin();
apiRegister("/api/temperature", "temperature", getDHTTemperature);
apiRegister("/api/humidity", "humidity", getDHTHumidity);
apiRegister("/api/temperature", "temperature", [](char * buffer, size_t len) {
dtostrf(_dhtTemperature, len-1, 1, buffer);
});
apiRegister("/api/humidity", "humidity", [](char * buffer, size_t len) {
snprintf(buffer, len, "%d", _dhtHumidity);
});
} }
void dhtLoop() { void dhtLoop() {
@ -52,25 +56,30 @@ void dhtLoop() {
} else { } else {
dtostrf(t, 4, 1, dhtTemperature);
itoa((int) h, dhtHumidity, 10);
_dhtTemperature = t;
_dhtHumidity = h;
DEBUG_MSG("[DHT] Temperature: %s\n", dhtTemperature);
DEBUG_MSG("[DHT] Humidity: %s\n", dhtHumidity);
char temperature[6];
char humidity[6];
dtostrf(t, 4, 1, temperature);
itoa((unsigned int) h, humidity, 10);
DEBUG_MSG("[DHT] Temperature: %s\n", temperature);
DEBUG_MSG("[DHT] Humidity: %s\n", humidity);
// Send MQTT messages // Send MQTT messages
mqttSend(getSetting("dhtTmpTopic", DHT_TEMPERATURE_TOPIC).c_str(), dhtTemperature);
mqttSend(getSetting("dhtHumTopic", DHT_HUMIDITY_TOPIC).c_str(), dhtHumidity);
mqttSend(getSetting("dhtTmpTopic", DHT_TEMPERATURE_TOPIC).c_str(), temperature);
mqttSend(getSetting("dhtHumTopic", DHT_HUMIDITY_TOPIC).c_str(), humidity);
// Send to Domoticz // Send to Domoticz
#if ENABLE_DOMOTICZ #if ENABLE_DOMOTICZ
domoticzSend("dczTmpIdx", dhtTemperature);
domoticzSend("dczHumIdx", dhtHumidity);
domoticzSend("dczTmpIdx", temperature);
domoticzSend("dczHumIdx", humidity);
#endif #endif
// Update websocket clients // Update websocket clients
char buffer[100]; char buffer[100];
sprintf_P(buffer, PSTR("{\"dhtVisible\": 1, \"dhtTmp\": %s, \"dhtHum\": %s}"), dhtTemperature, dhtHumidity);
sprintf_P(buffer, PSTR("{\"dhtVisible\": 1, \"dhtTmp\": %s, \"dhtHum\": %s}"), temperature, humidity);
wsSend(buffer); wsSend(buffer);
} }


+ 13
- 9
code/espurna/ds18b20.ino View File

@ -14,19 +14,21 @@ Copyright (C) 2016-2017 by Xose Pérez <xose dot perez at gmail dot com>
OneWire oneWire(DS_PIN); OneWire oneWire(DS_PIN);
DallasTemperature ds18b20(&oneWire); DallasTemperature ds18b20(&oneWire);
char dsTemperature[6];
double _dsTemperature = 0;
// ----------------------------------------------------------------------------- // -----------------------------------------------------------------------------
// DS18B20 // DS18B20
// ----------------------------------------------------------------------------- // -----------------------------------------------------------------------------
char * getDSTemperature() {
return dsTemperature;
double getDSTemperature() {
return _dsTemperature;
} }
void dsSetup() { void dsSetup() {
ds18b20.begin(); ds18b20.begin();
apiRegister("/api/temperature", "temperature", getDSTemperature);
apiRegister("/api/temperature", "temperature", [](char * buffer, size_t len) {
dtostrf(_dsTemperature, len-1, 1, buffer);
});
} }
void dsLoop() { void dsLoop() {
@ -49,21 +51,23 @@ void dsLoop() {
} else { } else {
dtostrf(t, 4, 1, dsTemperature);
_dsTemperature = t;
DEBUG_MSG("[DS18B20] Temperature: %s\n", dsTemperature);
char temperature[6];
dtostrf(t, 5, 1, temperature);
DEBUG_MSG("[DS18B20] Temperature: %s\n", temperature);
// Send MQTT messages // Send MQTT messages
mqttSend(getSetting("dsTmpTopic", DS_TEMPERATURE_TOPIC).c_str(), dsTemperature);
mqttSend(getSetting("dsTmpTopic", DS_TEMPERATURE_TOPIC).c_str(), temperature);
// Send to Domoticz // Send to Domoticz
#if ENABLE_DOMOTICZ #if ENABLE_DOMOTICZ
domoticzSend("dczTmpIdx", dsTemperature);
domoticzSend("dczTmpIdx", temperature);
#endif #endif
// Update websocket clients // Update websocket clients
char buffer[100]; char buffer[100];
sprintf_P(buffer, PSTR("{\"dsVisible\": 1, \"dsTmp\": %s}"), dsTemperature);
sprintf_P(buffer, PSTR("{\"dsVisible\": 1, \"dsTmp\": %s}"), temperature);
wsSend(buffer); wsSend(buffer);
} }


+ 27
- 20
code/espurna/emon.ino View File

@ -11,8 +11,8 @@ Copyright (C) 2016-2017 by Xose Pérez <xose dot perez at gmail dot com>
#include <EmonLiteESP.h> #include <EmonLiteESP.h>
EmonLiteESP emon; EmonLiteESP emon;
double current;
char power[8];
double _current = 0;
unsigned int _power = 0;
// ----------------------------------------------------------------------------- // -----------------------------------------------------------------------------
// EMON // EMON
@ -22,12 +22,12 @@ void setCurrentRatio(float value) {
emon.setCurrentRatio(value); emon.setCurrentRatio(value);
} }
char * getPower() {
return power;
unsigned int getPower() {
return _power;
} }
double getCurrent() { double getCurrent() {
return current;
return _current;
} }
unsigned int currentCallback() { unsigned int currentCallback() {
@ -53,7 +53,9 @@ void powerMonitorSetup() {
); );
emon.setPrecision(EMON_CURRENT_PRECISION); emon.setPrecision(EMON_CURRENT_PRECISION);
apiRegister("/api/power", "power", getPower);
apiRegister("/api/power", "power", [](char * buffer, size_t len) {
snprintf(buffer, len, "%d", _power);
});
} }
@ -77,41 +79,46 @@ void powerMonitorLoop() {
// Safety check: do not read current if relay is OFF // Safety check: do not read current if relay is OFF
if (!relayStatus(0)) { if (!relayStatus(0)) {
current = 0;
_current = 0;
} else { } else {
current = emon.getCurrent(EMON_SAMPLES);
current -= EMON_CURRENT_OFFSET;
if (current < 0) current = 0;
_current = emon.getCurrent(EMON_SAMPLES);
_current -= EMON_CURRENT_OFFSET;
if (_current < 0) _current = 0;
} }
if (measurements == 0) { if (measurements == 0) {
max = min = current;
max = min = _current;
} else { } else {
if (current > max) max = current;
if (current < min) min = current;
if (_current > max) max = _current;
if (_current < min) min = _current;
} }
sum += current;
sum += _current;
++measurements; ++measurements;
float mainsVoltage = getSetting("emonMains", EMON_MAINS_VOLTAGE).toFloat(); float mainsVoltage = getSetting("emonMains", EMON_MAINS_VOLTAGE).toFloat();
//DEBUG_MSG("[ENERGY] Power now: %dW\n", int(current * mainsVoltage));
//DEBUG_MSG("[ENERGY] Power now: %dW\n", int(_current * mainsVoltage));
// Update websocket clients // Update websocket clients
char text[20]; char text[20];
sprintf_P(text, PSTR("{\"emonPower\": %d}"), int(current * mainsVoltage));
sprintf_P(text, PSTR("{\"emonPower\": %d}"), int(_current * mainsVoltage));
wsSend(text); wsSend(text);
// Send MQTT messages averaged every EMON_MEASUREMENTS // Send MQTT messages averaged every EMON_MEASUREMENTS
if (measurements == EMON_MEASUREMENTS) { if (measurements == EMON_MEASUREMENTS) {
double p = (sum - max - min) * mainsVoltage / (measurements - 2);
sprintf(power, "%d", int(p));
_power = (int) ((sum - max - min) * mainsVoltage / (measurements - 2));
sum = 0;
measurements = 0;
char power[6];
snprintf(power, "%d", 6, _power);
mqttSend(getSetting("emonPowerTopic", EMON_POWER_TOPIC).c_str(), power); mqttSend(getSetting("emonPowerTopic", EMON_POWER_TOPIC).c_str(), power);
#if ENABLE_DOMOTICZ #if ENABLE_DOMOTICZ
domoticzSend("dczPowIdx", power); domoticzSend("dczPowIdx", power);
#endif #endif
sum = 0;
measurements = 0;
} }
next_measurement += EMON_INTERVAL; next_measurement += EMON_INTERVAL;


+ 6
- 9
code/espurna/pow.ino View File

@ -144,17 +144,14 @@ void powSetup() {
powAttachInterrupts(); powAttachInterrupts();
#endif #endif
apiRegister("/api/power", "power", []() {
sprintf(apibuffer, "%d", getActivePower());
return apibuffer;
apiRegister("/api/power", "power", [](char * buffer, size_t len) {
snprintf(buffer, len, "%d", getActivePower());
}); });
apiRegister("/api/current", "current", []() {
dtostrf(getCurrent(), 5, 2, apibuffer);
return apibuffer;
apiRegister("/api/current", "current", [](char * buffer, size_t len) {
dtostrf(getCurrent(), len-1, 2, buffer);
}); });
apiRegister("/api/voltage", "voltage", []() {
sprintf(apibuffer, "%d", getVoltage());
return apibuffer;
apiRegister("/api/voltage", "voltage", [](char * buffer, size_t len) {
snprintf(buffer, len, "%d", getVoltage());
}); });
} }


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

@ -181,8 +181,8 @@ void relaySetupAPI() {
sprintf(key, "relay%d", relayID); sprintf(key, "relay%d", relayID);
apiRegister(url, key, apiRegister(url, key,
[relayID]() {
return (char *) (relayStatus(relayID) ? "1" : "0");
[relayID](char * buffer, size_t len) {
snprintf(buffer, "%d", len, relayStatus(relayID) ? 1 : 0);
}, },
[relayID](const char * payload) { [relayID](const char * payload) {
unsigned int value = payload[0] - '0'; unsigned int value = payload[0] - '0';


+ 8
- 3
code/espurna/web.ino View File

@ -535,14 +535,19 @@ ArRequestHandlerFunction _bindAPI(unsigned int apiID) {
} }
} }
char * value = strdup((api.getFn)());
char value[10];
(api.getFn)(value, 10);
// jump over leading spaces
char *p = value;
while ((unsigned char) *p == ' ') ++p;
if (asJson) { if (asJson) {
char buffer[64]; char buffer[64];
sprintf_P(buffer, PSTR("{ \"%s\": %s }"), api.key, value);
sprintf_P(buffer, PSTR("{ \"%s\": %s }"), api.key, p);
request->send(200, "application/json", buffer); request->send(200, "application/json", buffer);
} else { } else {
request->send(200, "text/plain", value);
request->send(200, "text/plain", p);
} }
}; };


Loading…
Cancel
Save