espalexa robustness improvements
* prevent string buffer overflows (stack corruption) * avoid division by zero (program might crash) * avoid log(0) which is undefined, too * use faster math routines for float (logf, powf)
This commit is contained in:
parent
1c8f349a62
commit
a717238f76
@ -10,7 +10,7 @@
|
|||||||
*/
|
*/
|
||||||
/*
|
/*
|
||||||
* @title Espalexa library
|
* @title Espalexa library
|
||||||
* @version 2.7.0
|
* @version 2.7.1
|
||||||
* @author Christian Schwinne
|
* @author Christian Schwinne
|
||||||
* @license MIT
|
* @license MIT
|
||||||
* @contributors d-999
|
* @contributors d-999
|
||||||
@ -50,7 +50,7 @@
|
|||||||
#include "../network/Network.h"
|
#include "../network/Network.h"
|
||||||
|
|
||||||
#ifdef ESPALEXA_DEBUG
|
#ifdef ESPALEXA_DEBUG
|
||||||
#pragma message "Espalexa 2.7.0 debug mode"
|
#pragma message "Espalexa 2.7.1 debug mode"
|
||||||
#define EA_DEBUG(x) Serial.print (x)
|
#define EA_DEBUG(x) Serial.print (x)
|
||||||
#define EA_DEBUGLN(x) Serial.println (x)
|
#define EA_DEBUGLN(x) Serial.println (x)
|
||||||
#else
|
#else
|
||||||
@ -142,7 +142,7 @@ private:
|
|||||||
}
|
}
|
||||||
|
|
||||||
//device JSON string: color+temperature device emulates LCT015, dimmable device LWB010, (TODO: on/off Plug 01, color temperature device LWT010, color device LST001)
|
//device JSON string: color+temperature device emulates LCT015, dimmable device LWB010, (TODO: on/off Plug 01, color temperature device LWT010, color device LST001)
|
||||||
void deviceJsonString(EspalexaDevice* dev, char* buf)
|
void deviceJsonString(EspalexaDevice* dev, char* buf, size_t maxBuf) // softhack007 "size" parameter added, to avoid buffer overrun
|
||||||
{
|
{
|
||||||
char buf_lightid[27];
|
char buf_lightid[27];
|
||||||
encodeLightId(dev->getId() + 1, buf_lightid);
|
encodeLightId(dev->getId() + 1, buf_lightid);
|
||||||
@ -153,19 +153,19 @@ private:
|
|||||||
//TODO: %f is not working for some reason on ESP8266 in v0.11.0 (was fine in 0.10.2). Need to investigate
|
//TODO: %f is not working for some reason on ESP8266 in v0.11.0 (was fine in 0.10.2). Need to investigate
|
||||||
//sprintf_P(buf_col,PSTR(",\"hue\":%u,\"sat\":%u,\"effect\":\"none\",\"xy\":[%f,%f]")
|
//sprintf_P(buf_col,PSTR(",\"hue\":%u,\"sat\":%u,\"effect\":\"none\",\"xy\":[%f,%f]")
|
||||||
// ,dev->getHue(), dev->getSat(), dev->getX(), dev->getY());
|
// ,dev->getHue(), dev->getSat(), dev->getX(), dev->getY());
|
||||||
sprintf_P(buf_col,PSTR(",\"hue\":%u,\"sat\":%u,\"effect\":\"none\",\"xy\":[%s,%s]"),dev->getHue(), dev->getSat(),
|
snprintf_P(buf_col, sizeof(buf_col), PSTR(",\"hue\":%u,\"sat\":%u,\"effect\":\"none\",\"xy\":[%s,%s]"),dev->getHue(), dev->getSat(),
|
||||||
((String)dev->getX()).c_str(), ((String)dev->getY()).c_str());
|
((String)dev->getX()).c_str(), ((String)dev->getY()).c_str());
|
||||||
|
|
||||||
char buf_ct[16] = "";
|
char buf_ct[16] = "";
|
||||||
//white spectrum support
|
//white spectrum support
|
||||||
if (static_cast<uint8_t>(dev->getType()) > 1 && dev->getType() != EspalexaDeviceType::color)
|
if (static_cast<uint8_t>(dev->getType()) > 1 && dev->getType() != EspalexaDeviceType::color)
|
||||||
sprintf(buf_ct, ",\"ct\":%u", dev->getCt());
|
snprintf(buf_ct, sizeof(buf_ct), ",\"ct\":%u", dev->getCt());
|
||||||
|
|
||||||
char buf_cm[20] = "";
|
char buf_cm[20] = "";
|
||||||
if (static_cast<uint8_t>(dev->getType()) > 1)
|
if (static_cast<uint8_t>(dev->getType()) > 1)
|
||||||
sprintf(buf_cm,PSTR("\",\"colormode\":\"%s"), modeString(dev->getColorMode()));
|
snprintf(buf_cm, sizeof(buf_cm), PSTR("\",\"colormode\":\"%s"), modeString(dev->getColorMode()));
|
||||||
|
|
||||||
sprintf_P(buf, PSTR("{\"state\":{\"on\":%s,\"bri\":%u%s%s,\"alert\":\"none%s\",\"mode\":\"homeautomation\",\"reachable\":true},"
|
snprintf_P(buf, maxBuf, PSTR("{\"state\":{\"on\":%s,\"bri\":%u%s%s,\"alert\":\"none%s\",\"mode\":\"homeautomation\",\"reachable\":true},"
|
||||||
"\"type\":\"%s\",\"name\":\"%s\",\"modelid\":\"%s\",\"manufacturername\":\"Philips\",\"productname\":\"E%u"
|
"\"type\":\"%s\",\"name\":\"%s\",\"modelid\":\"%s\",\"manufacturername\":\"Philips\",\"productname\":\"E%u"
|
||||||
"\",\"uniqueid\":\"%s\",\"swversion\":\"espalexa-2.7.0\"}")
|
"\",\"uniqueid\":\"%s\",\"swversion\":\"espalexa-2.7.0\"}")
|
||||||
|
|
||||||
@ -219,10 +219,10 @@ private:
|
|||||||
EA_DEBUGLN("# Responding to description.xml ... #\n");
|
EA_DEBUGLN("# Responding to description.xml ... #\n");
|
||||||
IPAddress localIP = Network.localIP();
|
IPAddress localIP = Network.localIP();
|
||||||
char s[16];
|
char s[16];
|
||||||
sprintf(s, "%d.%d.%d.%d", localIP[0], localIP[1], localIP[2], localIP[3]);
|
snprintf(s, sizeof(s), "%d.%d.%d.%d", localIP[0], localIP[1], localIP[2], localIP[3]);
|
||||||
char buf[1024];
|
char buf[1024];
|
||||||
|
|
||||||
sprintf_P(buf,PSTR("<?xml version=\"1.0\" ?>"
|
snprintf_P(buf, sizeof(buf), PSTR("<?xml version=\"1.0\" ?>"
|
||||||
"<root xmlns=\"urn:schemas-upnp-org:device-1-0\">"
|
"<root xmlns=\"urn:schemas-upnp-org:device-1-0\">"
|
||||||
"<specVersion><major>1</major><minor>0</minor></specVersion>"
|
"<specVersion><major>1</major><minor>0</minor></specVersion>"
|
||||||
"<URLBase>http://%s:80/</URLBase>"
|
"<URLBase>http://%s:80/</URLBase>"
|
||||||
@ -297,7 +297,7 @@ private:
|
|||||||
|
|
||||||
char buf[1024];
|
char buf[1024];
|
||||||
|
|
||||||
sprintf_P(buf,PSTR("HTTP/1.1 200 OK\r\n"
|
snprintf_P(buf, sizeof(buf), PSTR("HTTP/1.1 200 OK\r\n"
|
||||||
"EXT:\r\n"
|
"EXT:\r\n"
|
||||||
"CACHE-CONTROL: max-age=100\r\n" // SSDP_INTERVAL
|
"CACHE-CONTROL: max-age=100\r\n" // SSDP_INTERVAL
|
||||||
"LOCATION: http://%s:80/description.xml\r\n"
|
"LOCATION: http://%s:80/description.xml\r\n"
|
||||||
@ -493,7 +493,7 @@ public:
|
|||||||
unsigned idx = decodeLightKey(devId);
|
unsigned idx = decodeLightKey(devId);
|
||||||
EA_DEBUGLN(idx);
|
EA_DEBUGLN(idx);
|
||||||
char buf[50];
|
char buf[50];
|
||||||
sprintf_P(buf,PSTR("[{\"success\":{\"/lights/%u/state/\": true}}]"),devId);
|
snprintf_P(buf,sizeof(buf),PSTR("[{\"success\":{\"/lights/%u/state/\": true}}]"),devId);
|
||||||
server->send(200, "application/json", buf);
|
server->send(200, "application/json", buf);
|
||||||
if (idx >= currentDeviceCount) return true; //return if invalid ID
|
if (idx >= currentDeviceCount) return true; //return if invalid ID
|
||||||
EspalexaDevice* dev = devices[idx];
|
EspalexaDevice* dev = devices[idx];
|
||||||
@ -571,7 +571,7 @@ public:
|
|||||||
jsonTemp += ':';
|
jsonTemp += ':';
|
||||||
|
|
||||||
char buf[512];
|
char buf[512];
|
||||||
deviceJsonString(devices[i], buf);
|
deviceJsonString(devices[i], buf, sizeof(buf)-1);
|
||||||
jsonTemp += buf;
|
jsonTemp += buf;
|
||||||
if (i < currentDeviceCount-1) jsonTemp += ',';
|
if (i < currentDeviceCount-1) jsonTemp += ',';
|
||||||
}
|
}
|
||||||
@ -588,7 +588,7 @@ public:
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
char buf[512];
|
char buf[512];
|
||||||
deviceJsonString(devices[idx], buf);
|
deviceJsonString(devices[idx], buf, sizeof(buf)-1);
|
||||||
server->send(200, "application/json", buf);
|
server->send(200, "application/json", buf);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2,6 +2,15 @@
|
|||||||
|
|
||||||
#include "EspalexaDevice.h"
|
#include "EspalexaDevice.h"
|
||||||
|
|
||||||
|
// debug macros
|
||||||
|
#ifdef ESPALEXA_DEBUG
|
||||||
|
#define EA_DEBUG(x) Serial.print (x)
|
||||||
|
#define EA_DEBUGLN(x) Serial.println (x)
|
||||||
|
#else
|
||||||
|
#define EA_DEBUG(x)
|
||||||
|
#define EA_DEBUGLN(x)
|
||||||
|
#endif
|
||||||
|
|
||||||
EspalexaDevice::EspalexaDevice(){}
|
EspalexaDevice::EspalexaDevice(){}
|
||||||
|
|
||||||
EspalexaDevice::EspalexaDevice(String deviceName, BrightnessCallbackFunction gnCallback, uint8_t initialValue) { //constructor for dimmable device
|
EspalexaDevice::EspalexaDevice(String deviceName, BrightnessCallbackFunction gnCallback, uint8_t initialValue) { //constructor for dimmable device
|
||||||
@ -124,18 +133,21 @@ uint32_t EspalexaDevice::getRGB()
|
|||||||
{
|
{
|
||||||
//TODO tweak a bit to match hue lamp characteristics
|
//TODO tweak a bit to match hue lamp characteristics
|
||||||
//based on https://gist.github.com/paulkaplan/5184275
|
//based on https://gist.github.com/paulkaplan/5184275
|
||||||
float temp = 10000/ _ct; //kelvins = 1,000,000/mired (and that /100)
|
float temp = (_ct != 0) ? (10000/ _ct) : 2; //kelvins = 1,000,000/mired (and that /100) softhack007: avoid division by zero - using "2" as substitute
|
||||||
float r, g, b;
|
float r, g, b;
|
||||||
|
|
||||||
|
#ifdef ESPALEXA_DEBUG
|
||||||
|
if (_ct == 0) {EA_DEBUGLN(F("EspalexaDevice::getRGB() Warning: ct = 0!"));}
|
||||||
|
#endif
|
||||||
if (temp <= 66) {
|
if (temp <= 66) {
|
||||||
r = 255;
|
r = 255;
|
||||||
g = temp;
|
g = temp;
|
||||||
g = 99.470802 * log(g) - 161.119568;
|
g = 99.470802 * logf(g) - 161.119568;
|
||||||
if (temp <= 19) {
|
if (temp <= 19) {
|
||||||
b = 0;
|
b = 0;
|
||||||
} else {
|
} else {
|
||||||
b = temp-10;
|
b = temp-10;
|
||||||
b = 138.517731 * log(b) - 305.044793;
|
b = 138.517731 * logf(b) - 305.044793;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
r = temp - 60;
|
r = temp - 60;
|
||||||
@ -192,9 +204,9 @@ uint32_t EspalexaDevice::getRGB()
|
|||||||
b = 1.0f;
|
b = 1.0f;
|
||||||
}
|
}
|
||||||
// Apply gamma correction
|
// Apply gamma correction
|
||||||
r = r <= 0.0031308f ? 12.92f * r : (1.0f + 0.055f) * pow(r, (1.0f / 2.4f)) - 0.055f;
|
r = r <= 0.0031308f ? 12.92f * r : (1.0f + 0.055f) * powf(r, (1.0f / 2.4f)) - 0.055f;
|
||||||
g = g <= 0.0031308f ? 12.92f * g : (1.0f + 0.055f) * pow(g, (1.0f / 2.4f)) - 0.055f;
|
g = g <= 0.0031308f ? 12.92f * g : (1.0f + 0.055f) * powf(g, (1.0f / 2.4f)) - 0.055f;
|
||||||
b = b <= 0.0031308f ? 12.92f * b : (1.0f + 0.055f) * pow(b, (1.0f / 2.4f)) - 0.055f;
|
b = b <= 0.0031308f ? 12.92f * b : (1.0f + 0.055f) * powf(b, (1.0f / 2.4f)) - 0.055f;
|
||||||
|
|
||||||
if (r > b && r > g) {
|
if (r > b && r > g) {
|
||||||
// red is biggest
|
// red is biggest
|
||||||
@ -328,8 +340,10 @@ void EspalexaDevice::setColor(uint8_t r, uint8_t g, uint8_t b)
|
|||||||
float X = r * 0.664511f + g * 0.154324f + b * 0.162028f;
|
float X = r * 0.664511f + g * 0.154324f + b * 0.162028f;
|
||||||
float Y = r * 0.283881f + g * 0.668433f + b * 0.047685f;
|
float Y = r * 0.283881f + g * 0.668433f + b * 0.047685f;
|
||||||
float Z = r * 0.000088f + g * 0.072310f + b * 0.986039f;
|
float Z = r * 0.000088f + g * 0.072310f + b * 0.986039f;
|
||||||
|
if ((r+g+b) > 0) { // softhack007: avoid division by zero
|
||||||
_x = X / (X + Y + Z);
|
_x = X / (X + Y + Z);
|
||||||
_y = Y / (X + Y + Z);
|
_y = Y / (X + Y + Z);
|
||||||
|
} else { _x = _y = 0.5f;} // softhack007: use default values in case of "black"
|
||||||
_rgb = ((r << 16) | (g << 8) | b);
|
_rgb = ((r << 16) | (g << 8) | b);
|
||||||
_mode = EspalexaColorMode::xy;
|
_mode = EspalexaColorMode::xy;
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user