Skip to content

Commit

Permalink
Merge pull request #2 from xoseperez/dev
Browse files Browse the repository at this point in the history
Merging back from Xoseperez
  • Loading branch information
ColinShorts authored May 16, 2018
2 parents c1c6d14 + 18c9082 commit e345597
Show file tree
Hide file tree
Showing 16 changed files with 3,309 additions and 3,111 deletions.
5 changes: 5 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -243,10 +243,15 @@ Here is the list of supported hardware. For more information please refer to the
|**Heltec Touch Relay**|**Generic Relay v4.0**|**Generic RGBLed v1.0**|
|![Generic DHT11 v1.0](images/devices/generic-dht11-10.jpg)|![Generic DS18B20 v1.0](images/devices/generic-ds18b20-10.jpg)||
|**Generic DHT11 v1.0**|**Generic DS18B20 v1.0**||
|![Tonbux Mosquito Killer](images/devices/tonbux-mosquito-killer.jpg)|||
|**Tonbux Mosquito Killer**|||

**Other supported boards:**
IteadStudio Sonoff S31, IteadStudio Sonoff POW R2, Zhilde ZLD-EU55-W, Luani HVIO

**Other supported boards (beta):**
KMC 4 Outlet, Gosund WS1, Smart Dual Plug, MakerFocus Intelligent Module LM33 for Lamps

## License

Copyright (C) 2016-2018 by Xose Pérez (@xoseperez)
Expand Down
1 change: 1 addition & 0 deletions code/espurna/config/arduino.h
Original file line number Diff line number Diff line change
Expand Up @@ -81,6 +81,7 @@
//#define ZHILDE_EU44_W
//#define LUANI_HVIO
//#define ALLNET_4DUINO_IOT_WLAN_RELAIS
//#define TONBUX_MOSQUITO_KILLER

//--------------------------------------------------------------------------------
// Features (values below are non-default values)
Expand Down
18 changes: 12 additions & 6 deletions code/espurna/config/general.h
Original file line number Diff line number Diff line change
Expand Up @@ -772,11 +772,8 @@
#define LIGHT_MAX_BRIGHTNESS 255 // Maximun brightness value
#endif

//#define LIGHT_MIN_MIREDS 153 // NOT USED (yet)! // Default to the Philips Hue value that HA has always assumed
//#define LIGHT_MAX_MIREDS 500 // NOT USED (yet)! // https://developers.meethue.com/documentation/core-concepts
#ifndef LIGHT_DEFAULT_MIREDS
#define LIGHT_DEFAULT_MIREDS 153 // Default value used by MQTT. This value is __NEVRER__ applied!
#endif
#define LIGHT_MIN_MIREDS 153 // Default to the Philips Hue value that HA also use.
#define LIGHT_MAX_MIREDS 500 // https://developers.meethue.com/documentation/core-concepts

#ifndef LIGHT_STEP
#define LIGHT_STEP 32 // Step size
Expand All @@ -787,9 +784,18 @@
#endif

#ifndef LIGHT_USE_WHITE
#define LIGHT_USE_WHITE 0 // Use white channel whenever RGB have the same value
#define LIGHT_USE_WHITE 0 // Use the 4th channel as (Warm-)White LEDs
#endif

#ifndef LIGHT_USE_CCT
#define LIGHT_USE_CCT 0 // Use the 5th channel as Coldwhite LEDs, LIGHT_USE_WHITE must be 1.
#endif

// Used when LIGHT_USE_WHITE AND LIGHT_USE_CCT is 1 - (1000000/Kelvin = MiReds)
// Warning! Don't change this yet, NOT FULLY IMPLEMENTED!
#define LIGHT_COLDWHITE_MIRED 153 // Coldwhite Strip, Value must be __BELOW__ W2!! (Default: 6535 Kelvin/153 MiRed)
#define LIGHT_WARMWHITE_MIRED 500 // Warmwhite Strip, Value must be __ABOVE__ W1!! (Default: 2000 Kelvin/500 MiRed)

#ifndef LIGHT_USE_GAMMA
#define LIGHT_USE_GAMMA 0 // Use gamma correction for color channels
#endif
Expand Down
36 changes: 36 additions & 0 deletions code/espurna/config/hardware.h
Original file line number Diff line number Diff line change
Expand Up @@ -1923,6 +1923,7 @@
#define DHT_SUPPORT 1
#endif
#define DHT_PIN 2
#define DHT_TYPE DHT_CHIP_DHT11

// -----------------------------------------------------------------------------
// ESP-01S DS18B20 v1.0
Expand Down Expand Up @@ -2072,6 +2073,41 @@
#define LED1_PIN 15
#define LED1_PIN_INVERSE 0

// -----------------------------------------------------------------------------
// Tonbux 50-100M Smart Mosquito Killer USB
// https://www.aliexpress.com/item/Original-Tonbux-50-100M-Smart-Mosquito-Killer-USB-Plug-No-Noise-Repellent-App-Smart-Module/32859330820.html
// -----------------------------------------------------------------------------

#elif defined(TONBUX_MOSQUITO_KILLER)

// Info
#define MANUFACTURER "TONBUX"
#define DEVICE "MOSQUITO_KILLER"

// Buttons
#define BUTTON1_PIN 2
#define BUTTON1_MODE BUTTON_PUSHBUTTON | BUTTON_DEFAULT_HIGH
#define BUTTON1_RELAY 1

// Relays
#define RELAY1_PIN 5 // not a relay, fan
#define RELAY1_TYPE RELAY_TYPE_NORMAL

// LEDs
#define LED1_PIN 15 // blue led
#define LED1_PIN_INVERSE 1
#define LED1_MODE LED_MODE_WIFI
#define LED2_PIN 14 // red led
#define LED2_PIN_INVERSE 1
#define LED2_MODE LED_MODE_RELAY

#define LED3_PIN 12 // UV leds (1-2-3-4-5-6-7-8)
#define LED3_PIN_INVERSE 0
#define LED3_RELAY 1
#define LED4_PIN 16 // UV leds (9-10-11)
#define LED4_PIN_INVERSE 0
#define LED4_RELAY 1

// -----------------------------------------------------------------------------
// TEST boards (do not use!!)
// -----------------------------------------------------------------------------
Expand Down
Binary file modified code/espurna/data/index.html.gz
Binary file not shown.
3 changes: 1 addition & 2 deletions code/espurna/homeassistant.ino
Original file line number Diff line number Diff line change
Expand Up @@ -24,9 +24,8 @@ void _haSendMagnitude(unsigned char i, JsonObject& config) {
unsigned char type = magnitudeType(i);
config["name"] = getSetting("hostname") + String(" ") + magnitudeTopic(type);
config.set("platform", "mqtt");
config.set("device_class", "sensor");
config["state_topic"] = mqttTopic(magnitudeTopicIndex(i).c_str(), false);
config["unit_of_measurement"] = String("\"") + magnitudeUnits(type) + String("\"");
config["unit_of_measurement"] = magnitudeUnits(type);

}

Expand Down
120 changes: 86 additions & 34 deletions code/espurna/light.ino
Original file line number Diff line number Diff line change
Expand Up @@ -40,10 +40,11 @@ bool _light_use_transitions = false;
unsigned int _light_transition_time = LIGHT_TRANSITION_TIME;
bool _light_has_color = false;
bool _light_use_white = false;
bool _light_use_cct = false;
bool _light_use_gamma = false;
unsigned long _light_steps_left = 1;
unsigned char _light_brightness = LIGHT_MAX_BRIGHTNESS;
unsigned int _light_mireds = LIGHT_DEFAULT_MIREDS;
unsigned int _light_mireds = round((LIGHT_COLDWHITE_MIRED+LIGHT_WARMWHITE_MIRED)/2);

#if LIGHT_PROVIDER == LIGHT_PROVIDER_MY92XX
#include <my92xx.h>
Expand Down Expand Up @@ -77,45 +78,70 @@ const unsigned char _light_gamma_table[] = {
// -----------------------------------------------------------------------------

void _setRGBInputValue(unsigned char red, unsigned char green, unsigned char blue) {
_light_channel[0].inputValue = red;
_light_channel[1].inputValue = green;
_light_channel[2].inputValue = blue;
_light_channel[0].inputValue = constrain(red, 0, LIGHT_MAX_VALUE);
_light_channel[1].inputValue = constrain(green, 0, LIGHT_MAX_VALUE);;
_light_channel[2].inputValue = constrain(blue, 0, LIGHT_MAX_VALUE);;
}

void _generateBrightness() {

double brightness = (double) _light_brightness / LIGHT_MAX_BRIGHTNESS;

// Convert RGB to RGBW
// Convert RGB to RGBW(W)
if (_light_has_color && _light_use_white) {

// Substract the common part from RGB channels and add it to white channel. So [250,150,50] -> [200,100,0,50
// Substract the common part from RGB channels and add it to white channel. So [250,150,50] -> [200,100,0,50]
unsigned char white = std::min(_light_channel[0].inputValue, std::min(_light_channel[1].inputValue, _light_channel[2].inputValue));
for (unsigned int i=0; i < 3; i++) {
_light_channel[i].value = _light_channel[i].inputValue - white;
}
_light_channel[3].value = white;
_light_channel[3].inputValue = 0;

// Split the White Value across 2 White LED Strips.
if (_light_use_cct) {

// This change the range from 153-500 to 0-347 so we get a value between 0 and 1 in the end.
double miredFactor = ((double) _light_mireds - (double) LIGHT_COLDWHITE_MIRED)/((double) LIGHT_WARMWHITE_MIRED - (double) LIGHT_COLDWHITE_MIRED);

// set cold white
_light_channel[3].inputValue = 0;
_light_channel[3].value = round(((double) 1.0 - miredFactor) * white);

// set warm white
_light_channel[4].inputValue = 0;
_light_channel[4].value = round(miredFactor * white);
} else {
_light_channel[3].inputValue = 0;
_light_channel[3].value = white;
}

// Scale up to equal input values. So [250,150,50] -> [200,100,0,50] -> [250, 125, 0, 63]
unsigned char max_in = std::max(_light_channel[0].inputValue, std::max(_light_channel[1].inputValue, _light_channel[2].inputValue));
unsigned char max_out = std::max(std::max(_light_channel[0].value, _light_channel[1].value), std::max(_light_channel[2].value, _light_channel[3].value));
unsigned char channelSize = _light_use_cct ? 5 : 4;

if (_light_use_cct) {
max_out = std::max(max_out, _light_channel[4].value);
}

double factor = (max_out > 0) ? (double) (max_in / max_out) : 0;
for (unsigned int i=0; i < 4; i++) {
for (unsigned char i=0; i < channelSize; i++) {
_light_channel[i].value = round((double) _light_channel[i].value * factor * brightness);
}

// Scale white channel to match brightness
_light_channel[3].value = constrain(_light_channel[3].value * LIGHT_WHITE_FACTOR, 0, 255);
for (unsigned char i=3; i < channelSize; i++) {
_light_channel[i].value = constrain(_light_channel[i].value * LIGHT_WHITE_FACTOR, 0, LIGHT_MAX_BRIGHTNESS);
}

// For the rest of channels, don't apply brightness, it is already in the inputValue:
for (unsigned char i=4; i < _light_channel.size(); i++) {
// For the rest of channels, don't apply brightness, it is already in the inputValue
// i should be 4 when RGBW and 5 when RGBWW
for (unsigned char i=channelSize; i < _light_channel.size(); i++) {
_light_channel[i].value = _light_channel[i].inputValue;
}

} else {

// Don't apply brightness, it is already in the inputValue:
// Don't apply brightness, it is already in the target:
for (unsigned char i=0; i < _light_channel.size(); i++) {
if (_light_has_color & (i<3)) {
_light_channel[i].value = _light_channel[i].inputValue * brightness;
Expand Down Expand Up @@ -155,16 +181,10 @@ void _fromRGB(const char * rgb) {
}
break;
case 'M': // Mired Value
if (_light_has_color) {
unsigned long mireds = atol(p + 1);
_fromMireds(mireds);
}
_fromMireds(atol(p + 1));
break;
case 'K': // Kelvin Value
if (_light_has_color) {
unsigned long kelvin = atol(p + 1);
_fromKelvin(kelvin);
}
_fromKelvin(atol(p + 1));
break;
default: // assume decimal values separated by commas
char * tok;
Expand Down Expand Up @@ -257,13 +277,18 @@ void _fromHSV(const char * hsv) {
// https://github.com/stelgenhof/AiLight
void _fromKelvin(unsigned long kelvin, bool setMireds) {

// Check we have RGB channels
if (!_light_has_color) return;

if (setMireds) {
_light_mireds = round(1000000UL / kelvin);
_light_mireds = constrain(round(1000000UL / kelvin), LIGHT_MIN_MIREDS, LIGHT_MAX_MIREDS);
}

if (_light_use_cct) {
_setRGBInputValue(LIGHT_MAX_VALUE, LIGHT_MAX_VALUE, LIGHT_MAX_VALUE);
return;
}


// Calculate colors
unsigned int red = (kelvin <= 66)
? LIGHT_MAX_VALUE
Expand All @@ -277,11 +302,7 @@ void _fromKelvin(unsigned long kelvin, bool setMireds) {
? 0
: 138.5177312231 * log(kelvin - 10) - 305.0447927307);

_setRGBInputValue(
constrain(red, 0, LIGHT_MAX_VALUE),
constrain(green, 0, LIGHT_MAX_VALUE),
constrain(blue, 0, LIGHT_MAX_VALUE)
);
_setRGBInputValue(red, green, blue);
}

void _fromKelvin(unsigned long kelvin) {
Expand All @@ -290,8 +311,15 @@ void _fromKelvin(unsigned long kelvin) {

// Color temperature is measured in mireds (kelvin = 1e6/mired)
void _fromMireds(unsigned long mireds) {
if (mireds == 0) mireds = 1;
_light_mireds = mireds;
if (!_light_has_color) return;

_light_mireds = mireds = constrain(mireds, LIGHT_MIN_MIREDS, LIGHT_MAX_MIREDS);

if (_light_use_cct) {
_setRGBInputValue(LIGHT_MAX_VALUE, LIGHT_MAX_VALUE, LIGHT_MAX_VALUE);
return;
}

unsigned long kelvin = constrain(1000000UL / mireds, 1000, 40000) / 100;
_fromKelvin(kelvin, false);
}
Expand All @@ -313,15 +341,15 @@ void _toRGB(char * rgb, size_t len) {
}

void _toHSV(char * hsv, size_t len) {
double min, max, h, s, v;
double h, s, v;
double brightness = (double) _light_brightness / LIGHT_MAX_BRIGHTNESS;

double r = (double) (_light_channel[0].inputValue * brightness) / 255.0;
double g = (double) (_light_channel[1].inputValue * brightness) / 255.0;
double b = (double) (_light_channel[2].inputValue * brightness) / 255.0;

min = std::min(r, std::min(g, b));
max = std::max(r, std::max(g, b));
double min = std::min(r, std::min(g, b));
double max = std::max(r, std::max(g, b));

v = 100.0 * max;
if (v == 0) {
Expand Down Expand Up @@ -389,22 +417,28 @@ unsigned int _toPWM(unsigned char id) {
}

void _shadow() {

// Update transition ticker
_light_steps_left--;
if (_light_steps_left == 0) _light_transition_ticker.detach();

// Transitions
unsigned char target;
for (unsigned int i=0; i < _light_channel.size(); i++) {
target = _light_state ? _light_channel[i].value : 0;

target = _light_state && _light_channel[i].state ? _light_channel[i].value : 0;

if (_light_steps_left == 0) {
_light_channel[i].current = target;
} else {
double difference = (double) (target - _light_channel[i].current) / (_light_steps_left + 1);
_light_channel[i].current = _light_channel[i].current + difference;
}

_light_channel[i].shadow = _light_channel[i].current;

}

}

void _lightProviderUpdate() {
Expand Down Expand Up @@ -441,6 +475,7 @@ void _lightColorSave() {
setSetting("ch", i, _light_channel[i].inputValue);
}
setSetting("brightness", _light_brightness);
setSetting("mireds", _light_mireds);
saveSettings();
}

Expand All @@ -449,6 +484,7 @@ void _lightColorRestore() {
_light_channel[i].inputValue = getSetting("ch", i, i==0 ? 255 : 0).toInt();
}
_light_brightness = getSetting("brightness", LIGHT_MAX_BRIGHTNESS).toInt();
_light_mireds = getSetting("mireds", _light_mireds).toInt();
lightUpdate(false, false);
}

Expand Down Expand Up @@ -751,6 +787,10 @@ void _lightWebSocketOnSend(JsonObject& root) {
bool useRGB = getSetting("useRGB", LIGHT_USE_RGB).toInt() == 1;
root["useRGB"] = useRGB;
if (_light_has_color) {
if (_light_use_cct) {
root["useCCT"] = _light_use_cct;
root["mireds"] = _light_mireds;
}
if (useRGB) {
root["rgb"] = lightColor(true);
root["brightness"] = lightBrightness();
Expand Down Expand Up @@ -780,6 +820,12 @@ void _lightWebSocketOnAction(uint32_t client_id, const char * action, JsonObject
lightUpdate(true, true);
}
}
if (_light_use_cct) {
if (strcmp(action, "mireds") == 0) {
_fromMireds(data["mireds"]);
lightUpdate(true, true);
}
}
}

if (strcmp(action, "channel") == 0) {
Expand Down Expand Up @@ -961,6 +1007,12 @@ void _lightConfigure() {
setSetting("useWhite", _light_use_white);
}

_light_use_cct = getSetting("useCCT", LIGHT_USE_CCT).toInt() == 1;
if (_light_use_cct && ((_light_channel.size() < 5) || !_light_use_white)) {
_light_use_cct = false;
setSetting("useCCT", _light_use_cct);
}

_light_use_gamma = getSetting("useGamma", LIGHT_USE_GAMMA).toInt() == 1;
_light_use_transitions = getSetting("useTransitions", LIGHT_USE_TRANSITIONS).toInt() == 1;
_light_transition_time = getSetting("lightTime", LIGHT_TRANSITION_TIME).toInt();
Expand Down
Loading

0 comments on commit e345597

Please sign in to comment.