Browse Source

light: refactor to use namespace(s)

Also clamp the value in setters / getters.
pull/2471/head
Maxim Prokhorov 2 years ago
parent
commit
d482baa725
2 changed files with 330 additions and 137 deletions
  1. +330
    -46
      code/espurna/light.cpp
  2. +0
    -91
      code/espurna/light_config.h

+ 330
- 46
code/espurna/light.cpp View File

@ -45,8 +45,6 @@ extern "C" {
#endif
#include "light_config.h"
// -----------------------------------------------------------------------------
namespace Light {
@ -70,6 +68,291 @@ unsigned long Rgb::asUlong() const {
return (_red << 16) | (_green << 8) | _blue;
}
namespace {
namespace build {
constexpr bool relay() {
return 1 == LIGHT_RELAY_ENABLED;
}
constexpr bool color() {
return 1 == LIGHT_USE_COLOR;
}
constexpr bool white() {
return 1 == LIGHT_USE_WHITE;
}
constexpr bool cct() {
return 1 == LIGHT_USE_CCT;
}
constexpr bool rgb() {
return 1 == LIGHT_USE_RGB;
}
constexpr bool gamma() {
return 1 == LIGHT_USE_GAMMA;
}
constexpr bool transition() {
return 1 == LIGHT_USE_TRANSITIONS;
}
constexpr unsigned long transitionTime() {
return LIGHT_TRANSITION_TIME;
}
constexpr unsigned long transitionStep() {
return LIGHT_TRANSITION_STEP;
}
constexpr bool save() {
return 1 == LIGHT_SAVE_ENABLED;
}
constexpr unsigned long saveDelay() {
return LIGHT_SAVE_DELAY;
}
constexpr unsigned char enablePin() {
return LIGHT_ENABLE_PIN;
}
constexpr unsigned char channelPin(size_t index) {
return (
(index == 0) ? LIGHT_CH1_PIN :
(index == 1) ? LIGHT_CH2_PIN :
(index == 2) ? LIGHT_CH3_PIN :
(index == 3) ? LIGHT_CH4_PIN :
(index == 4) ? LIGHT_CH5_PIN : GPIO_NONE
);
}
constexpr bool inverse(size_t index) {
return (
(index == 0) ? (1 == LIGHT_CH1_INVERSE) :
(index == 1) ? (1 == LIGHT_CH2_INVERSE) :
(index == 2) ? (1 == LIGHT_CH3_INVERSE) :
(index == 3) ? (1 == LIGHT_CH4_INVERSE) :
(index == 4) ? (1 == LIGHT_CH5_INVERSE) : false
);
}
#if LIGHT_PROVIDER == LIGHT_PROVIDER_MY92XX
constexpr my92xx_cmd_t my92xxCommand() {
return MY92XX_COMMAND;
}
constexpr size_t my92xxChannels() {
return MY92XX_CHANNELS;
}
constexpr my92xx_model_t my92xxModel() {
return MY92XX_MODEL;
}
constexpr int my92xxChips() {
return MY92XX_CHIPS;
}
constexpr int my92xxDiPin() {
return MY92XX_DI_PIN;
}
constexpr int my92xxDckiPin() {
return MY92XX_DCKI_PIN;
}
#if defined(MY92XX_MAPPING)
namespace my92xx {
constexpr unsigned char mapping[MY92XX_CHANNELS] {
MY92XX_MAPPING
};
template <typename... T>
struct FailSafe {
static constexpr bool value { false };
};
constexpr unsigned char channel(T channel) {
static_assert(FailSafe<T>::value, "MY92XX_CH# flags should be used instead of MY92XX_MAPPING");
return mapping[channel];
}
} // namespace my92xx
constexpr unsigned char my92xxChannel(size_t channel) {
return my92xx::channel(channel);
}
#else // !defined(MY92XX_MAPPING)
constexpr unsigned char my92xxChannel(size_t channel) {
return (channel == 0) ? MY92XX_CH1 :
(channel == 1) ? MY92XX_CH2 :
(channel == 2) ? MY92XX_CH3 :
(channel == 3) ? MY92XX_CH4 :
(channel == 4) ? MY92XX_CH5 : Light::ChannelsMax;
}
#endif
#endif
} // namespace build
namespace settings {
unsigned char enablePin() {
return getSetting("ltEnableGPIO", Light::build::enablePin());
}
#if LIGHT_PROVIDER == LIGHT_PROVIDER_DIMMER
unsigned char channelPin(size_t index) {
return getSetting({"ltDimmerGPIO", index}, build::channelPin(index));
}
#endif
bool inverse(size_t index) {
return getSetting({"ltInv", index}, build::inverse(index));
}
#if LIGHT_PROVIDER == LIGHT_PROVIDER_MY92XX
size_t my92xxChannels() {
return getSetting("ltMy92xxChannels", build::my92xxChannels());
}
my92xx_model_t my92xxModel() {
return getSetting("ltMy92xxModel", build::my92xxModel());
}
int my92xxChips() {
return getSetting("ltMy92xxChips", build::my92xxChips());
}
int my92xxDiPin() {
return getSetting("ltMy92xxDiGPIO", build::my92xxDiPin());
}
int my92xxDckiPin() {
return getSetting("ltMy92xxDckiGPIO", build::my92xxDckiPin());
}
unsigned char my92xxChannel(size_t channel) {
return getSetting({"ltMy92xxCh", channel}, build::my92xxChannel(channel));
}
#endif
long value(size_t channel) {
const long defaultValue { (channel == 0) ? Light::ValueMax : Light::ValueMin };
return std::clamp(getSetting({"ch", channel}, defaultValue), Light::ValueMin, Light::ValueMax);
}
void value(size_t channel, long input) {
setSetting({"ch", channel}, std::clamp(input, Light::ValueMin, Light::ValueMax));
}
long mireds() {
return std::clamp(getSetting("mireds", Light::MiredsDefault), Light::MiredsCold, Light::MiredsWarm);
}
long miredsCold() {
return getSetting("ltColdMired", Light::MiredsCold);
}
long miredsWarm() {
return getSetting("ltWarmMired", Light::MiredsWarm);
}
void mireds(long value) {
setSetting("mireds", std::clamp(value, Light::MiredsCold, Light::MiredsWarm));
}
long brightness() {
return std::clamp(getSetting("brightness", Light::BrightnessMax), Light::BrightnessMin, Light::BrightnessMax);
}
void brightness(long value) {
setSetting("brightness", std::clamp(value, Light::BrightnessMin, Light::BrightnessMax));
}
String mqttGroup() {
return getSetting("mqttGroupColor");
}
bool relay() {
return getSetting("ltRelay", build::relay());
}
bool color() {
return getSetting("useColor", build::color());
}
void color(bool value) {
setSetting("useColor", value);
}
bool white() {
return getSetting("useWhite", build::white());
}
void white(bool value) {
setSetting("useWhite", value);
}
bool cct() {
return getSetting("useCCT", build::cct());
}
void cct(bool value) {
setSetting("useCCT", value);
}
bool rgb() {
return getSetting("useRGB", build::rgb());
}
bool gamma() {
return getSetting("useGamma", build::gamma());
}
bool transition() {
return getSetting("useTransitions", build::transition());
}
void transition(bool value) {
setSetting("useTransitions", value);
}
unsigned long transitionTime() {
return getSetting("ltTime", build::transitionTime());
}
void transitionTime(unsigned long value) {
setSetting("ltTime", value);
}
unsigned long transitionStep() {
return getSetting("ltStep", build::transitionStep());
}
void transitionStep(unsigned long value) {
setSetting("ltStep", value);
}
bool save() {
return getSetting("ltSave", build::save());
}
unsigned long saveDelay() {
return getSetting("ltSaveDelay", build::saveDelay());
}
} // namespace settings
} // namespace
} // namespace Light
// -----------------------------------------------------------------------------
@ -1291,23 +1574,22 @@ void _lightSaveSettings() {
}
for (size_t channel = 0; channel < lightChannels(); ++channel) {
setSetting({"ch", channel}, _light_channels[channel].inputValue);
Light::settings::value(channel, _light_channels[channel].inputValue);
}
setSetting("brightness", _light_brightness);
setSetting("mireds", _light_mireds);
Light::settings::brightness(_light_brightness);
Light::settings::mireds(_light_mireds);
saveSettings();
}
void _lightRestoreSettings() {
for (size_t channel = 0; channel < lightChannels(); ++channel) {
auto value = getSetting({"ch", channel}, (channel == 0) ? Light::ValueMax : Light::ValueMin);
_light_channels[channel].inputValue = value;
_light_mapping.set(&_light_channels[channel], Light::settings::value(channel));
}
_light_mireds = getSetting("mireds", _light_mireds);
lightBrightness(getSetting("brightness", Light::BrightnessMax));
_light_mireds = Light::settings::mireds();
lightBrightness(Light::settings::brightness());
}
bool _lightParsePayload(const char* payload) {
@ -1376,8 +1658,7 @@ bool _lightMqttHeartbeat(heartbeat::Mask mask) {
}
void _lightMqttCallback(unsigned int type, const char * topic, const char * payload) {
String mqtt_group_color = getSetting("mqttGroupColor");
String mqtt_group_color = Light::settings::mqttGroup();
if (type == MQTT_CONNECT_EVENT) {
@ -1525,7 +1806,7 @@ void lightMQTT() {
}
void lightMQTTGroup() {
const String mqtt_group_color = getSetting("mqttGroupColor");
const String mqtt_group_color = Light::settings::mqttGroup();
if (mqtt_group_color.length()) {
mqttSendRaw(mqtt_group_color.c_str(), _lightGroupPayload(false).c_str());
}
@ -1714,7 +1995,7 @@ void _lightWebSocketOnVisible(JsonObject& root) {
}
void _lightWebSocketOnConnected(JsonObject& root) {
root["mqttGroupColor"] = getSetting("mqttGroupColor");
root["mqttGroupColor"] = Light::settings::mqttGroup();
root["useColor"] = _light_has_color;
root["useWhite"] = _light_use_white;
root["useGamma"] = _light_use_gamma;
@ -1725,7 +2006,7 @@ void _lightWebSocketOnConnected(JsonObject& root) {
root["ltTime"] = _light_transition_time;
root["ltStep"] = _light_transition_step;
#if RELAY_SUPPORT
root["ltRelay"] = getSetting("ltRelay", 1 == LIGHT_RELAY_ENABLED);
root["ltRelay"] = Light::settings::relay();
#endif
}
@ -2290,10 +2571,10 @@ void lightTransition(unsigned long time, unsigned long step) {
_light_transition_step = step;
}
setSetting("useTransitions", _light_use_transitions);
Light::settings::transition(_light_use_transitions);
if (save) {
setSetting("ltTime", _light_transition_time);
setSetting("ltStep", _light_transition_step);
Light::settings::transitionTime(_light_transition_time);
Light::settings::transitionStep(_light_transition_step);
}
saveSettings();
@ -2344,16 +2625,16 @@ inline bool _lightUseGamma(size_t index) {
void _lightConfigure() {
auto channels = _light_channels.size();
_light_has_color = getSetting("useColor", 1 == LIGHT_USE_COLOR);
_light_has_color = Light::settings::color();
if (_light_has_color && (channels < 3)) {
_light_has_color = false;
setSetting("useColor", _light_has_color);
Light::settings::color(false);
}
_light_use_white = getSetting("useWhite", 1 == LIGHT_USE_WHITE);
_light_use_white = Light::settings::white();
if (_light_use_white && (channels < 4) && (channels != 2)) {
_light_use_white = false;
setSetting("useWhite", _light_use_white);
Light::settings::white(false);
}
if (_light_has_color) {
@ -2366,31 +2647,32 @@ void _lightConfigure() {
_light_brightness_func = _lightApplyBrightnessAll;
}
_light_use_cct = getSetting("useCCT", 1 == LIGHT_USE_CCT);
_light_use_cct = Light::settings::cct();
if (_light_use_cct && (((channels < 5) && (channels != 2)) || !_light_use_white)) {
_light_use_cct = false;
setSetting("useCCT", _light_use_cct);
Light::settings::cct(false);
}
_light_use_rgb = getSetting("useRGB", 1 == LIGHT_USE_RGB);
_light_use_rgb = Light::settings::rgb();
_light_cold_mireds = getSetting("ltColdMired", Light::MiredsCold);
_light_warm_mireds = getSetting("ltWarmMired", Light::MiredsWarm);
_light_cold_mireds = Light::settings::miredsCold();
_light_warm_mireds = Light::settings::miredsWarm();
_light_cold_kelvin = (1000000L / _light_cold_mireds);
_light_warm_kelvin = (1000000L / _light_warm_mireds);
_light_use_transitions = getSetting("useTransitions", 1 == LIGHT_USE_TRANSITIONS);
_light_save = getSetting("ltSave", 1 == LIGHT_SAVE_ENABLED);
_light_save_delay = getSetting("ltSaveDelay", LIGHT_SAVE_DELAY);
_light_transition_time = getSetting("ltTime", LIGHT_TRANSITION_TIME);
_light_transition_step = getSetting("ltStep", LIGHT_TRANSITION_STEP);
_light_use_transitions = Light::settings::transition();
_light_transition_time = Light::settings::transitionTime();
_light_transition_step = Light::settings::transitionStep();
_light_save = Light::settings::save();
_light_save_delay = Light::settings::saveDelay();
_light_use_gamma = getSetting("useGamma", 1 == LIGHT_USE_GAMMA);
_light_use_gamma = Light::settings::gamma();
for (size_t index = 0; index < lightChannels(); ++index) {
#if LIGHT_PROVIDER == LIGHT_PROVIDER_MY92XX
_light_my92xx_channel_map[index] = getSetting({"ltMy92xxCh", index}, Light::build::my92xxChannel(index));
_light_my92xx_channel_map[index] = Light::settings::my92xxChannel(index);
#endif
_light_channels[index].inverse = getSetting({"ltInv", index}, Light::build::inverse(index));
_light_channels[index].inverse = Light::settings::inverse(index);
_light_channels[index].gamma = (_light_has_color && _light_use_gamma) && _lightUseGamma(channels, index);
}
@ -2399,7 +2681,7 @@ void _lightConfigure() {
#if RELAY_SUPPORT
void _lightRelaySupport() {
if (!getSetting("ltRelay", 1 == LIGHT_RELAY_ENABLED)) {
if (!Light::settings::relay()) {
return;
}
@ -2526,7 +2808,7 @@ void _lightSettingsMigrate(int version) {
void lightSetup() {
migrateVersion(_lightSettingsMigrate);
const auto enable_pin = getSetting("ltEnableGPIO", Light::build::enablePin());
const auto enable_pin = Light::settings::enablePin();
if (enable_pin != GPIO_NONE) {
pinMode(enable_pin, OUTPUT);
digitalWrite(enable_pin, HIGH);
@ -2540,15 +2822,17 @@ void lightSetup() {
// TODO: library API specifies some hard-coded amount of channels, based off of the model and chips
// we always map channel index 1-to-1, to simplify hw config, but most of the time there are less active channels
// than the value generated by the lib (ref. `my92xx::getChannels()`)
auto channels = getSetting("ltMy92xxChannels", Light::build::my92xxChannels());
_my92xx = new my92xx(
getSetting("ltMy92xxModel", Light::build::my92xxModel()),
getSetting("ltMy92xxChips", Light::build::my92xxChips()),
getSetting("ltMy92xxDiGPIO", Light::build::my92xxDiPin()),
getSetting("ltMy92xxDckiGPIO", Light::build::my92xxDckiPin()),
Light::build::my92xxCommand());
for (size_t index = 0; index < channels; ++index) {
_light_channels.emplace_back(GPIO_NONE);
auto channels = Light::settings::my92xxChannels();
if (channels) {
_my92xx = new my92xx(
Light::settings::my92xxModel(),
Light::settings::my92xxChips(),
Light::settings::my92xxDiPin(),
Light::settings::my92xxDckiPin(),
Light::build::my92xxCommand());
for (size_t index = 0; index < channels; ++index) {
_light_channels.emplace_back(GPIO_NONE);
}
}
}
#elif LIGHT_PROVIDER == LIGHT_PROVIDER_DIMMER
@ -2562,7 +2846,7 @@ void lightSetup() {
for (size_t index = 0; index < Light::ChannelsMax; ++index) {
// Load up until first GPIO_NONE. Allow settings to override, but not remove values
const auto pin = getSetting({"ltDimmerGPIO", index}, Light::build::channelPin(index));
const auto pin = Light::settings::channelPin(index);
if (!gpioValid(pin)) {
break;
}


+ 0
- 91
code/espurna/light_config.h View File

@ -1,91 +0,0 @@
/*
LIGHT MODULE
*/
#pragma once
#include "espurna.h"
namespace Light {
namespace build {
constexpr unsigned char enablePin() {
return LIGHT_ENABLE_PIN;
}
constexpr unsigned char channelPin(size_t index) {
return (
(index == 0) ? LIGHT_CH1_PIN :
(index == 1) ? LIGHT_CH2_PIN :
(index == 2) ? LIGHT_CH3_PIN :
(index == 3) ? LIGHT_CH4_PIN :
(index == 4) ? LIGHT_CH5_PIN : GPIO_NONE
);
}
constexpr bool inverse(size_t index) {
return (
(index == 0) ? (1 == LIGHT_CH1_INVERSE) :
(index == 1) ? (1 == LIGHT_CH2_INVERSE) :
(index == 2) ? (1 == LIGHT_CH3_INVERSE) :
(index == 3) ? (1 == LIGHT_CH4_INVERSE) :
(index == 4) ? (1 == LIGHT_CH5_INVERSE) : false
);
}
#if LIGHT_PROVIDER == LIGHT_PROVIDER_MY92XX
constexpr my92xx_cmd_t my92xxCommand() {
return MY92XX_COMMAND;
}
constexpr size_t my92xxChannels() {
return MY92XX_CHANNELS;
}
constexpr my92xx_model_t my92xxModel() {
return MY92XX_MODEL;
}
constexpr int my92xxChips() {
return MY92XX_CHIPS;
}
constexpr int my92xxDiPin() {
return MY92XX_DI_PIN;
}
constexpr int my92xxDckiPin() {
return MY92XX_DCKI_PIN;
}
#ifdef MY92XX_MAPPING
constexpr unsigned char _my92xx_mapping[MY92XX_CHANNELS] {
MY92XX_MAPPING
};
constexpr unsigned char my92xxChannel(size_t)
__attribute__((deprecated("MY92XX_CH# flags should be used instead of MY92XX_MAPPING")));
constexpr unsigned char my92xxChannel(size_t channel) {
return _my92xx_mapping[channel];
}
#else
constexpr unsigned char my92xxChannel(size_t channel) {
return (channel == 0) ? MY92XX_CH1 :
(channel == 1) ? MY92XX_CH2 :
(channel == 2) ? MY92XX_CH3 :
(channel == 3) ? MY92XX_CH4 :
(channel == 4) ? MY92XX_CH5 : Light::ChannelsMax;
}
#endif
#endif
} // namespace build
} // namespace Light

Loading…
Cancel
Save