Browse Source

light: experiment with relay state provider

* dynamic relays should not overlap with configuration
* prefer explicit relay configuration vs. dynamic addition

resolve #2568
pull/2575/head
Maxim Prokhorov 1 year ago
parent
commit
b5a03dac72
33 changed files with 12024 additions and 11965 deletions
  1. +0
    -4
      code/espurna/config/general.h
  2. +101
    -2
      code/espurna/config/hardware.h
  3. +1
    -0
      code/espurna/config/types.h
  4. +1
    -1
      code/espurna/config/version.h
  5. BIN
      code/espurna/data/index.all.html.gz
  6. BIN
      code/espurna/data/index.curtain.html.gz
  7. BIN
      code/espurna/data/index.garland.html.gz
  8. BIN
      code/espurna/data/index.light.html.gz
  9. BIN
      code/espurna/data/index.lightfox.html.gz
  10. BIN
      code/espurna/data/index.rfbridge.html.gz
  11. BIN
      code/espurna/data/index.rfm69.html.gz
  12. BIN
      code/espurna/data/index.sensor.html.gz
  13. BIN
      code/espurna/data/index.small.html.gz
  14. BIN
      code/espurna/data/index.thermostat.html.gz
  15. +3
    -1
      code/espurna/ifan.cpp
  16. +34
    -86
      code/espurna/light.cpp
  17. +3
    -0
      code/espurna/light.h
  18. +2
    -2
      code/espurna/lightfox.cpp
  19. +97
    -24
      code/espurna/relay.cpp
  20. +10
    -45
      code/espurna/relay.h
  21. +1897
    -1900
      code/espurna/static/index.all.html.gz.h
  22. +1042
    -1042
      code/espurna/static/index.curtain.html.gz.h
  23. +1002
    -1002
      code/espurna/static/index.garland.html.gz.h
  24. +1597
    -1600
      code/espurna/static/index.light.html.gz.h
  25. +1005
    -1005
      code/espurna/static/index.lightfox.html.gz.h
  26. +1037
    -1037
      code/espurna/static/index.rfbridge.html.gz.h
  27. +1041
    -1041
      code/espurna/static/index.rfm69.html.gz.h
  28. +1136
    -1137
      code/espurna/static/index.sensor.html.gz.h
  29. +989
    -990
      code/espurna/static/index.small.html.gz.h
  30. +1024
    -1024
      code/espurna/static/index.thermostat.html.gz.h
  31. +2
    -4
      code/html/custom.css
  32. +0
    -10
      code/html/custom.js
  33. +0
    -8
      code/html/index.html

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

@ -1214,10 +1214,6 @@
#define LIGHT_TRANSITION_TIME 500 // Time in millis from color to color
#endif
#ifndef LIGHT_RELAY_ENABLED
#define LIGHT_RELAY_ENABLED 1 // Add a virtual switch that controls the global light state. Depends on RELAY_SUPPORT
#endif
// -----------------------------------------------------------------------------
// DOMOTICZ
// -----------------------------------------------------------------------------


+ 101
- 2
code/espurna/config/hardware.h View File

@ -827,6 +827,9 @@
#define DEVICE "BNSZ01"
#define LIGHT_PROVIDER LIGHT_PROVIDER_DIMMER
// Relay
#define RELAY1_PROVIDER RELAY_PROVIDER_LIGHT_STATE
// LEDs
#define LED1_PIN 13
#define LED1_PIN_INVERSE 1
@ -876,6 +879,9 @@
#define DEVICE "SONOFF_B1"
#define LIGHT_PROVIDER LIGHT_PROVIDER_MY92XX
// Relay
#define RELAY1_PROVIDER RELAY_PROVIDER_LIGHT_STATE
// Light
#define MY92XX_MODEL MY92XX_MODEL_MY9231
@ -900,6 +906,9 @@
#define DEVICE "SONOFF_LED"
#define LIGHT_PROVIDER LIGHT_PROVIDER_DIMMER
// Relay
#define RELAY1_PROVIDER RELAY_PROVIDER_LIGHT_STATE
// LEDs
#define LED1_PIN 13
#define LED1_PIN_INVERSE 1
@ -1304,6 +1313,9 @@
#define DEVICE "AI_LIGHT"
#define LIGHT_PROVIDER LIGHT_PROVIDER_MY92XX
// Relay
#define RELAY1_PROVIDER RELAY_PROVIDER_LIGHT_STATE
// Light
#define MY92XX_MODEL MY92XX_MODEL_MY9291
#define MY92XX_CHIPS 1
@ -1323,6 +1335,9 @@
#define DEVICE "RGB_LED"
#define LIGHT_PROVIDER LIGHT_PROVIDER_MY92XX
// Relay
#define RELAY1_PROVIDER RELAY_PROVIDER_LIGHT_STATE
// Light
#define MY92XX_MODEL MY92XX_MODEL_MY9291
#define MY92XX_CHIPS 1
@ -1342,6 +1357,9 @@
#define DEVICE "LED_CONTROLLER"
#define LIGHT_PROVIDER LIGHT_PROVIDER_DIMMER
// Relay
#define RELAY1_PROVIDER RELAY_PROVIDER_LIGHT_STATE
// LEDs
#define LED1_PIN 2
#define LED1_PIN_INVERSE 1
@ -1365,6 +1383,9 @@
#define DEVICE "LED_CONTROLLER_20"
#define LIGHT_PROVIDER LIGHT_PROVIDER_DIMMER
// Relay
#define RELAY1_PROVIDER RELAY_PROVIDER_LIGHT_STATE
// LEDs
#define LED1_PIN 2
#define LED1_PIN_INVERSE 1
@ -1388,6 +1409,9 @@
#define DEVICE "ZJ_WFMN_A_11"
#define LIGHT_PROVIDER LIGHT_PROVIDER_DIMMER
// Relay
#define RELAY1_PROVIDER RELAY_PROVIDER_LIGHT_STATE
// LEDs
#define LED1_PIN 2
#define LED1_PIN_INVERSE 1
@ -1413,6 +1437,9 @@
#define DEVICE "ZJ_WFMN_B_11"
#define LIGHT_PROVIDER LIGHT_PROVIDER_DIMMER
// Relay
#define RELAY1_PROVIDER RELAY_PROVIDER_LIGHT_STATE
// LEDs
#define LED1_PIN 2
#define LED1_PIN_INVERSE 1
@ -1437,6 +1464,9 @@
#define DEVICE "ZJ_WFMN_C_11"
#define LIGHT_PROVIDER LIGHT_PROVIDER_DIMMER
// Relay
#define RELAY1_PROVIDER RELAY_PROVIDER_LIGHT_STATE
// Buttons
#define BUTTON1_PIN 0
#define BUTTON1_CONFIG BUTTON_PUSHBUTTON | BUTTON_DEFAULT_HIGH
@ -1456,6 +1486,9 @@
#define DEVICE "ZJ_ESPM_5CH_B_13"
#define LIGHT_PROVIDER LIGHT_PROVIDER_DIMMER
// Relay
#define RELAY1_PROVIDER RELAY_PROVIDER_LIGHT_STATE
// Buttons
#define BUTTON1_PIN 0
#define BUTTON1_CONFIG BUTTON_PUSHBUTTON | BUTTON_DEFAULT_HIGH
@ -1479,6 +1512,9 @@
#define DEVICE "ZJ_LB_RGBWW_L"
#define LIGHT_PROVIDER LIGHT_PROVIDER_DIMMER
// Relay
#define RELAY1_PROVIDER RELAY_PROVIDER_LIGHT_STATE
// Light
#define LIGHT_CH1_PIN 5 // RED
#define LIGHT_CH2_PIN 4 // GREEN
@ -1497,6 +1533,9 @@
#define DEVICE "H801"
#define LIGHT_PROVIDER LIGHT_PROVIDER_DIMMER
// Relay
#define RELAY1_PROVIDER RELAY_PROVIDER_LIGHT_STATE
// Debug
#define UART1_TX_PIN 2
#define UART2_RX_PIN GPIO_NONE
@ -1519,6 +1558,9 @@
#define DEVICE "H802"
#define LIGHT_PROVIDER LIGHT_PROVIDER_DIMMER
// Relay
#define RELAY1_PROVIDER RELAY_PROVIDER_LIGHT_STATE
// Debug
#define UART1_TX_PIN 2
#define UART2_RX_PIN GPIO_NONE
@ -1906,6 +1948,9 @@
#define DEVICE "QUINLED"
#define LIGHT_PROVIDER LIGHT_PROVIDER_DIMMER
// Relay
#define RELAY1_PROVIDER RELAY_PROVIDER_LIGHT_STATE
// LEDs
#define LED1_PIN 5
#define LED1_PIN_INVERSE 1
@ -1925,6 +1970,9 @@
#define DEVICE "AL_LC01"
#define LIGHT_PROVIDER LIGHT_PROVIDER_DIMMER
// Relay
#define RELAY1_PROVIDER RELAY_PROVIDER_LIGHT_STATE
// Light
#define LIGHT_CH1_PIN 5 // RED
#define LIGHT_CH2_PIN 12 // GREEN
@ -1937,6 +1985,9 @@
#define DEVICE "AL_LC02"
#define LIGHT_PROVIDER LIGHT_PROVIDER_DIMMER
// Relay
#define RELAY1_PROVIDER RELAY_PROVIDER_LIGHT_STATE
// Light
#define LIGHT_CH1_PIN 12 // RED
#define LIGHT_CH2_PIN 5 // GREEN
@ -1950,6 +2001,9 @@
#define DEVICE "AL_LC02_V14"
#define LIGHT_PROVIDER LIGHT_PROVIDER_DIMMER
// Relay
#define RELAY1_PROVIDER RELAY_PROVIDER_LIGHT_STATE
// Light
#define LIGHT_CH1_PIN 14 // RED
#define LIGHT_CH2_PIN 5 // GREEN
@ -1963,6 +2017,9 @@
#define DEVICE "AL_LC06"
#define LIGHT_PROVIDER LIGHT_PROVIDER_DIMMER
// Relay
#define RELAY1_PROVIDER RELAY_PROVIDER_LIGHT_STATE
// Buttons
#define BUTTON1_PIN 0
#define BUTTON1_CONFIG BUTTON_PUSHBUTTON | BUTTON_DEFAULT_HIGH
@ -1982,6 +2039,9 @@
#define DEVICE "AL_LC11"
#define LIGHT_PROVIDER LIGHT_PROVIDER_DIMMER
// Relay
#define RELAY1_PROVIDER RELAY_PROVIDER_LIGHT_STATE
// Light
#define LIGHT_CH1_PIN 5 // RED
#define LIGHT_CH2_PIN 4 // GREEN
@ -1996,6 +2056,9 @@
#define DEVICE "E27"
#define LIGHT_PROVIDER LIGHT_PROVIDER_MY92XX
// Relay
#define RELAY1_PROVIDER RELAY_PROVIDER_LIGHT_STATE
// Light
#define MY92XX_MODEL MY92XX_MODEL_MY9291
#define MY92XX_CHIPS 1
@ -2064,6 +2127,9 @@
#define DEVICE "LYT8266"
#define LIGHT_PROVIDER LIGHT_PROVIDER_DIMMER
// Relay
#define RELAY1_PROVIDER RELAY_PROVIDER_LIGHT_STATE
// Light
#define LIGHT_CH1_PIN 13 // RED
#define LIGHT_CH2_PIN 12 // GREEN
@ -2079,6 +2145,9 @@
#define DEVICE "WITTY_CLOUD"
#define LIGHT_PROVIDER LIGHT_PROVIDER_DIMMER
// Relay
#define RELAY1_PROVIDER RELAY_PROVIDER_LIGHT_STATE
// Buttons
#define BUTTON1_PIN 4
#define BUTTON1_CONFIG BUTTON_PUSHBUTTON | BUTTON_DEFAULT_HIGH
@ -3708,6 +3777,9 @@
#define DEVICE "AG_L4"
#define LIGHT_PROVIDER LIGHT_PROVIDER_DIMMER
// Relay
#define RELAY1_PROVIDER RELAY_PROVIDER_LIGHT_STATE
// button 1: "power" button
#define BUTTON1_PIN 4
#define BUTTON1_RELAY 1
@ -3749,6 +3821,9 @@
#define DEVICE "AG_L4_V3"
#define LIGHT_PROVIDER LIGHT_PROVIDER_DIMMER
// Relay
#define RELAY1_PROVIDER RELAY_PROVIDER_LIGHT_STATE
// button 1: "power" button
#define BUTTON1_PIN 13
#define BUTTON1_RELAY 1
@ -4298,8 +4373,10 @@
#define BUTTON1_RELAY 1
// Relays
#define RELAY1_PIN 15
#define RELAY1_TYPE RELAY_TYPE_NORMAL
#define RELAY1_PROVIDER RELAY_PROVIDER_LIGHT_STATE
#define RELAY2_PIN 15
#define RELAY2_TYPE RELAY_TYPE_NORMAL
// LEDs
//Red LED: 0
@ -4522,6 +4599,9 @@
#define DEVICE "RGBW_CONTROLLER"
#define LIGHT_PROVIDER LIGHT_PROVIDER_DIMMER
// Relay
#define RELAY1_PROVIDER RELAY_PROVIDER_LIGHT_STATE
// LEDs
#define LED1_PIN 13
#define LED1_PIN_INVERSE 1
@ -4597,6 +4677,7 @@
#define TUYA_CH1_DPID 2
#define LIGHT_PROVIDER LIGHT_PROVIDER_CUSTOM
#define RELAY1_PROVIDER RELAY_PROVIDER_NONE
#define LED1_GPIO 14
@ -4728,6 +4809,9 @@
#define DEVICE "MIOBULB001"
#define LIGHT_PROVIDER LIGHT_PROVIDER_DIMMER
// Relay
#define RELAY1_PROVIDER RELAY_PROVIDER_LIGHT_STATE
// Light
#define LIGHT_CH1_PIN 14 // RED
#define LIGHT_CH2_PIN 12 // GREEN
@ -4857,6 +4941,9 @@
#define DEVICE "SMART_LED_LIGHT_STRIP"
#define LIGHT_PROVIDER LIGHT_PROVIDER_DIMMER
// Relay
#define RELAY1_PROVIDER RELAY_PROVIDER_LIGHT_STATE
// Light RGBW
#define LIGHT_CH1_PIN 4 // RED
#define LIGHT_CH2_PIN 12 // GREEN
@ -5073,6 +5160,9 @@
#define DEVICE "E27_7W_RGBW"
#define LIGHT_PROVIDER LIGHT_PROVIDER_DIMMER
// Relay
#define RELAY1_PROVIDER RELAY_PROVIDER_LIGHT_STATE
// Light
#define LIGHT_CH1_PIN 4 // RED
#define LIGHT_CH2_PIN 12 // GREEN
@ -5091,6 +5181,9 @@
#define DEVICE "GU53_RGBWW"
#define LIGHT_PROVIDER LIGHT_PROVIDER_DIMMER
// Relay
#define RELAY1_PROVIDER RELAY_PROVIDER_LIGHT_STATE
// Light
#define LIGHT_CH1_PIN 4 // RED
#define LIGHT_CH2_PIN 12 // GREEN
@ -5109,6 +5202,9 @@
#define DEVICE "E27_10W_WHITE"
#define LIGHT_PROVIDER LIGHT_PROVIDER_DIMMER
// Relay
#define RELAY1_PROVIDER RELAY_PROVIDER_LIGHT_STATE
// Light
#define LIGHT_CH1_PIN 5 // WARM WHITE
#define LIGHT_CH2_PIN 4 // COLD WHITE
@ -5127,6 +5223,9 @@
#define DEVICE "GENIO_W_A60"
#define LIGHT_PROVIDER LIGHT_PROVIDER_DIMMER
// Relay
#define RELAY1_PROVIDER RELAY_PROVIDER_LIGHT_STATE
// Light
#define LIGHT_CH1_PIN 14 // WHITE


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

@ -106,6 +106,7 @@
#define RELAY_PROVIDER_GPIO RelayProvider::Gpio
#define RELAY_PROVIDER_DUAL RelayProvider::Dual
#define RELAY_PROVIDER_STM RelayProvider::Stm
#define RELAY_PROVIDER_LIGHT_STATE RelayProvider::LightState
#define RFB_PROVIDER_RCSWITCH 0
#define RFB_PROVIDER_EFM8BB1 1


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

@ -21,5 +21,5 @@
#endif
#ifndef CFG_VERSION
#define CFG_VERSION 13
#define CFG_VERSION 14
#endif

BIN
code/espurna/data/index.all.html.gz View File


BIN
code/espurna/data/index.curtain.html.gz View File


BIN
code/espurna/data/index.garland.html.gz View File


BIN
code/espurna/data/index.light.html.gz View File


BIN
code/espurna/data/index.lightfox.html.gz View File


BIN
code/espurna/data/index.rfbridge.html.gz View File


BIN
code/espurna/data/index.rfm69.html.gz View File


BIN
code/espurna/data/index.sensor.html.gz View File


BIN
code/espurna/data/index.small.html.gz View File


BIN
code/espurna/data/index.thermostat.html.gz View File


+ 3
- 1
code/espurna/ifan.cpp View File

@ -324,7 +324,9 @@ void setup() {
if (relay_pin) {
auto provider = std::make_unique<FanProvider>(
std::move(relay_pin), config, state_pins, onFanSpeedUpdate);
if (!relayAdd(std::move(provider))) {
const auto result = relayAdd(std::move(provider));
if (result) {
DEBUG_MSG_P(PSTR("[IFAN] Could not add relay provider for GPIO%d\n"), controlPin());
gpioUnlock(controlPin());
}


+ 34
- 86
code/espurna/light.cpp View File

@ -65,10 +65,6 @@ namespace build {
constexpr float WhiteFactor { LIGHT_WHITE_FACTOR };
constexpr bool relay() {
return 1 == LIGHT_RELAY_ENABLED;
}
constexpr bool color() {
return 1 == LIGHT_USE_COLOR;
}
@ -287,10 +283,6 @@ String mqttGroup() {
return getSetting("mqttGroupColor");
}
bool relay() {
return getSetting("ltRelay", build::relay());
}
bool color() {
return getSetting("useColor", build::color());
}
@ -364,34 +356,10 @@ espurna::duration::Milliseconds saveDelay() {
#if RELAY_SUPPORT
// Setup virtual relays contolling the light's state
// TODO: only do per-channel setup optionally
class LightChannelProvider : public RelayProviderBase {
public:
LightChannelProvider() = delete;
explicit LightChannelProvider(size_t id) :
_id(id)
{}
const char* id() const override {
return "light_channel";
}
void change(bool status) override {
lightState(_id, status);
lightState(true);
lightUpdate();
}
private:
size_t _id { RelaysMax };
};
class LightGlobalProvider : public RelayProviderBase {
class LightStateProvider : public RelayProviderBase {
public:
const char* id() const override {
return "light_global";
espurna::StringView id() const override {
return STRING_VIEW("light-state");
}
void change(bool status) override {
@ -706,7 +674,6 @@ auto _light_report_delay = espurna::light::build::reportDelay();
std::forward_list<LightReportListener> _light_report;
LightTimerValue<int> _light_report_timer(0);
bool _light_has_controls = false;
bool _light_has_cold_white = false;
bool _light_has_warm_white = false;
bool _light_has_color = false;
@ -2330,10 +2297,7 @@ void _lightMqttCallback(unsigned int type, espurna::StringView topic, espurna::S
mqttSubscribe(MQTT_TOPIC_CHANNEL "/+");
mqttSubscribe(MQTT_TOPIC_BRIGHTNESS);
if (!_light_has_controls) {
mqttSubscribe(MQTT_TOPIC_LIGHT);
}
mqttSubscribe(MQTT_TOPIC_LIGHT);
if (_light_has_color) {
mqttSubscribe(MQTT_TOPIC_COLOR_RGB);
@ -2447,10 +2411,7 @@ void lightMQTT() {
}
mqttSend(MQTT_TOPIC_BRIGHTNESS, _light_brightness.toString().c_str());
if (!_light_has_controls) {
mqttSend(MQTT_TOPIC_LIGHT, _light_state ? "1" : "0");
}
mqttSend(MQTT_TOPIC_LIGHT, _light_state ? "1" : "0");
}
void lightMQTTGroup() {
@ -2585,19 +2546,17 @@ void _lightApiSetup() {
}
);
if (!_light_has_controls) {
apiRegister(F(MQTT_TOPIC_LIGHT),
[](ApiRequest& request) {
request.send(lightState() ? "1" : "0");
return true;
},
[](ApiRequest& request) {
_lightParsePayload(request.param(F("value")));
lightUpdate();
return true;
}
);
}
apiRegister(F(MQTT_TOPIC_LIGHT),
[](ApiRequest& request) {
request.send(lightState() ? "1" : "0");
return true;
},
[](ApiRequest& request) {
_lightParsePayload(request.param(F("value")));
lightUpdate();
return true;
}
);
}
} // namespace
@ -2672,11 +2631,6 @@ void _lightWebSocketOnConnected(JsonObject& root) {
root["ltSaveDelay"] = _light_save_delay.count();
root["ltTime"] = _light_transition_time.count();
root["ltStep"] = _light_transition_step.count();
#if RELAY_SUPPORT
root["ltRelay"] = espurna::light::settings::relay();
#else
root["ltRelay"] = false;
#endif
}
void _lightWebSocketOnAction(uint32_t client_id, const char* action, JsonObject& data) {
@ -3523,24 +3477,6 @@ void _lightConfigure() {
}
}
#if RELAY_SUPPORT
void _lightRelayBoot() {
if (_light_has_controls) {
return;
}
auto next_id = relayCount();
if (relayAdd(std::make_unique<LightGlobalProvider>())) {
_light_state_listener = [next_id](bool state) {
relayStatus(next_id, state);
};
_light_has_controls = true;
}
}
#endif
void _lightBoot() {
const size_t Channels { _light_channels.size() };
if (Channels) {
@ -3640,12 +3576,30 @@ void _lightSettingsMigrate(int version) {
moveSetting("lightColdMired", "ltColdMired");
moveSetting("lightWarmMired", "ltWarmMired");
}
if (version < 14) {
delSetting(F("ltRelay"));
}
}
} // namespace
// -----------------------------------------------------------------------------
RelayProviderBasePtr lightMakeStateRelayProvider(size_t id) {
#if RELAY_SUPPORT
if (!_light_state_listener) {
_light_state_listener = [id](bool state) {
relayStatus(id, state);
};
return std::make_unique<LightStateProvider>();
}
#endif
return nullptr;
}
void lightSetup() {
migrateVersion(_lightSettingsMigrate);
@ -3701,12 +3655,6 @@ void lightSetup() {
_lightBoot();
#if RELAY_SUPPORT
if (espurna::light::settings::relay()) {
_lightRelayBoot();
}
#endif
#if WEB_SUPPORT
wsRegister()
.onVisible(_lightWebSocketOnVisible)


+ 3
- 0
code/espurna/light.h View File

@ -278,4 +278,7 @@ void lightOnReport(LightReportListener);
void lightSetProvider(std::unique_ptr<LightProvider>&&);
bool lightAdd();
class RelayProviderBase;
std::unique_ptr<RelayProviderBase> lightMakeStateRelayProvider(size_t);
void lightSetup();

+ 2
- 2
code/espurna/lightfox.cpp View File

@ -257,8 +257,8 @@ void setup() {
#endif
for (size_t relay = 0; relay < build::relays(); ++relay) {
size_t relayId { relayCount() };
if (!relayAdd(std::make_unique<RelayProvider>(relayId))) {
const auto result = relayAdd(std::make_unique<RelayProvider>(relay));
if (!result) {
break;
}
}


+ 97
- 24
code/espurna/relay.cpp View File

@ -16,6 +16,7 @@ Copyright (C) 2019-2021 by Maxim Prokhorov <prokhorov dot max at outlook dot com
#include "relay.h"
#include "rpc.h"
#include "rtcmem.h"
#include "light.h"
#include "settings.h"
#include "storage_eeprom.h"
#include "terminal.h"
@ -31,6 +32,50 @@ Copyright (C) 2019-2021 by Maxim Prokhorov <prokhorov dot max at outlook dot com
// -----------------------------------------------------------------------------
enum class RelayBoot {
Off,
On,
Same,
Toggle,
LockedOff,
LockedOn
};
enum class RelayLock {
None,
Off,
On
};
enum class RelayType {
Normal,
Inverse,
Latched,
LatchedInverse
};
enum class RelayMqttTopicMode {
Normal,
Inverse
};
enum class RelayProvider {
None,
Dummy,
Gpio,
Dual,
Stm,
LightState,
};
enum class RelaySync {
None,
ZeroOrOne,
JustOne,
All,
First
};
namespace espurna {
namespace relay {
namespace flood {
@ -597,13 +642,15 @@ PROGMEM_STRING(RelayProviderDummy, "dummy");
PROGMEM_STRING(RelayProviderGpio, "gpio");
PROGMEM_STRING(RelayProviderDual, "dual");
PROGMEM_STRING(RelayProviderStm, "stm");
PROGMEM_STRING(RelayProviderLightState, "light-state");
static constexpr std::array<Enumeration<RelayProvider>, 5> RelayProviderOptions PROGMEM {
static constexpr std::array<Enumeration<RelayProvider>, 6> RelayProviderOptions PROGMEM {
{{RelayProvider::None, RelayProviderNone},
{RelayProvider::Dummy, RelayProviderDummy},
{RelayProvider::Gpio, RelayProviderGpio},
{RelayProvider::Dual, RelayProviderDual},
{RelayProvider::Stm, RelayProviderStm}}
{RelayProvider::Dummy, RelayProviderDummy},
{RelayProvider::Gpio, RelayProviderGpio},
{RelayProvider::Dual, RelayProviderDual},
{RelayProvider::Stm, RelayProviderStm},
{RelayProvider::LightState, RelayProviderLightState}}
};
PROGMEM_STRING(RelayTypeNormal, "normal");
@ -998,8 +1045,8 @@ static constexpr espurna::settings::query::IndexedSetting IndexedSettings[] PROG
// No-op provider, available for purely virtual relays that are controlled only via API
struct DummyProvider : public RelayProviderBase {
const char* id() const override {
return "dummy";
espurna::StringView id() const override {
return espurna::relay::settings::options::RelayProviderDummy;
}
void change(bool) override {
@ -1229,8 +1276,8 @@ struct GpioProvider : public RelayProviderBase {
_reset_pin(std::move(reset_pin))
{}
const char* id() const override {
return "gpio";
espurna::StringView id() const override {
return espurna::relay::settings::options::RelayProviderGpio;
}
bool setup() override {
@ -1301,8 +1348,8 @@ public:
_instances.end());
}
const char* id() const override {
return "dual";
espurna::StringView id() const override {
return espurna::relay::settings::options::RelayProviderDual;
}
bool setup() override {
@ -1412,10 +1459,11 @@ public:
_id(id)
{}
const char* id() const override {
return "stm";
espurna::StringView id() const override {
return espurna::relay::settings::options::RelayProviderStm;
}
bool setup() override {
static bool once = ([]() {
const auto port = uartPort(RELAY_PROVIDER_STM_PORT - 1);
@ -2570,8 +2618,9 @@ String _relayTristateToPayload(T value) {
}
void _relayPrint(Print& out, const Relay& relay, size_t index) {
out.printf_P(PSTR("relay%u {Prov=%s TargetStatus=%s CurrentStatus=%s Lock=%s}\n"),
index, relay.provider->id(),
out.printf_P(PSTR("relay%u {Prov=%.*s TargetStatus=%s CurrentStatus=%s Lock=%s}\n"),
index,
relay.provider->id().length(), relay.provider->id().begin(),
relay.target_status ? "on" : "off",
relay.current_status ? "on" : "off",
_relayTristateToPayload(relay.lock).c_str());
@ -2860,19 +2909,29 @@ RelayProviderBasePtr _relaySetupProvider(size_t index) {
case RelayProvider::Dummy:
result = std::make_unique<DummyProvider>();
break;
case RelayProvider::Gpio:
result = _relayGpioProvider(index, type);
break;
case RelayProvider::Stm:
#if RELAY_PROVIDER_STM_SUPPORT
result = std::make_unique<StmProvider>(index);
#endif
break;
case RelayProvider::Dual:
#if RELAY_PROVIDER_DUAL_SUPPORT
result = std::make_unique<DualProvider>(index);
#endif
break;
case RelayProvider::LightState:
#if LIGHT_PROVIDER != LIGHT_PROVIDER_NONE
result = lightMakeStateRelayProvider(index);
#endif
break;
case RelayProvider::None:
break;
}
@ -2976,17 +3035,31 @@ void relaySetup() {
}
bool relayAdd(RelayProviderBasePtr&& provider) {
if (provider && provider->setup()) {
_relays.emplace_back(std::move(provider));
espurnaRegisterOnceUnique([]() {
_relayConfigure();
_relayBootAll();
});
return true;
RelayAddResult relayAdd(RelayProviderBasePtr&& provider) {
RelayAddResult out;
const auto id = _relays.size();
if (espurna::relay::settings::provider(id) != RelayProvider::None) {
return out;
}
return false;
if (!provider) {
return out;
}
if (!provider->setup()) {
return out;
}
out.id = id;
_relays.emplace_back(std::move(provider));
espurnaRegisterOnceUnique([]() {
_relayConfigure();
_relayBootAll();
});
return out;
}
#endif // RELAY_SUPPORT == 1

+ 10
- 45
code/espurna/relay.h View File

@ -18,49 +18,6 @@ Copyright (C) 2016-2019 by Xose Pérez <xose dot perez at gmail dot com>
constexpr size_t RelaysMax { 32ul };
enum class RelayBoot {
Off,
On,
Same,
Toggle,
LockedOff,
LockedOn
};
enum class RelayLock {
None,
Off,
On
};
enum class RelayType {
Normal,
Inverse,
Latched,
LatchedInverse
};
enum class RelayMqttTopicMode {
Normal,
Inverse
};
enum class RelayProvider {
None,
Dummy,
Gpio,
Dual,
Stm
};
enum class RelaySync {
None,
ZeroOrOne,
JustOne,
All,
First
};
class RelayProviderBase {
public:
RelayProviderBase() = default;
@ -79,7 +36,7 @@ public:
virtual void change(bool status) = 0;
// unique id of the provider
virtual const char* id() const = 0;
virtual espurna::StringView id() const = 0;
};
PayloadStatus relayParsePayload(espurna::StringView);
@ -113,7 +70,15 @@ void relaySave(bool persist);
using RelayStatusCallback = void(*)(size_t id, bool status);
using RelayProviderBasePtr = std::unique_ptr<RelayProviderBase>;
bool relayAdd(RelayProviderBasePtr&& provider);
struct RelayAddResult {
size_t id { RelaysMax };
explicit operator bool() const {
return id != RelaysMax;
}
};
RelayAddResult relayAdd(RelayProviderBasePtr&& provider);
void relayOnStatusNotify(RelayStatusCallback);
void relayOnStatusChange(RelayStatusCallback);


+ 1897
- 1900
code/espurna/static/index.all.html.gz.h
File diff suppressed because it is too large
View File


+ 1042
- 1042
code/espurna/static/index.curtain.html.gz.h
File diff suppressed because it is too large
View File


+ 1002
- 1002
code/espurna/static/index.garland.html.gz.h
File diff suppressed because it is too large
View File


+ 1597
- 1600
code/espurna/static/index.light.html.gz.h
File diff suppressed because it is too large
View File


+ 1005
- 1005
code/espurna/static/index.lightfox.html.gz.h
File diff suppressed because it is too large
View File


+ 1037
- 1037
code/espurna/static/index.rfbridge.html.gz.h
File diff suppressed because it is too large
View File


+ 1041
- 1041
code/espurna/static/index.rfm69.html.gz.h
File diff suppressed because it is too large
View File


+ 1136
- 1137
code/espurna/static/index.sensor.html.gz.h
File diff suppressed because it is too large
View File


+ 989
- 990
code/espurna/static/index.small.html.gz.h
File diff suppressed because it is too large
View File


+ 1024
- 1024
code/espurna/static/index.thermostat.html.gz.h
File diff suppressed because it is too large
View File


+ 2
- 4
code/html/custom.css View File

@ -614,15 +614,13 @@ input::placeholder {
}
#light-cct,
#light-picker,
#light-state {
#light-picker {
display: none;
}
#light.light-cct #light-cct,
#light.light-cct:not(.light-white) #light-channel-c,
#light.light-cct:not(.light-white) #light-channel-w,
#light.light-color.light-on:not(.light-cct) #light-picker,
#light.light-state #light-state {
#light.light-color.light-on:not(.light-cct) #light-picker {
display: block;
}

+ 0
- 10
code/html/custom.js View File

@ -2170,12 +2170,6 @@ function colorUpdate(mode, value) {
}
}
function lightStateEnabled(value) {
if (!value) {
lightAddClass("light-state");
}
}
function initLightState() {
const toggle = document.getElementById("light-state-value");
toggle.addEventListener("change", (event) => {
@ -2643,10 +2637,6 @@ function processData(data) {
return;
}
if ("ltRelay" === key) {
lightStateEnabled(value);
}
if ("useWhite" === key) {
whiteEnabled(value);
}


+ 0
- 8
code/html/index.html View File

@ -632,14 +632,6 @@
<fieldset>
<div class="pure-control-group module module-relay">
<label>Light state switch</label>
<div><input type="checkbox" name="ltRelay"></div>
<span class="pure-form-message">
Add a virtual relay switch that controls the ON / OFF state.
</span>
</div>
<div class="pure-control-group">
<label>Save values</label>
<div><input type="checkbox" name="ltSave"></div>


Loading…
Cancel
Save