Browse Source

ifan: more fixes, clean-up relays

mcspr-patch-1
Maxim Prokhorov 3 years ago
parent
commit
2223184c25
3 changed files with 95 additions and 50 deletions
  1. +5
    -0
      code/espurna/config/dependencies.h
  2. +1
    -4
      code/espurna/config/hardware.h
  3. +89
    -46
      code/espurna/ifan.cpp

+ 5
- 0
code/espurna/config/dependencies.h View File

@ -132,6 +132,11 @@
#define MQTT_SUPPORT 1 // Subscribe and publish things #define MQTT_SUPPORT 1 // Subscribe and publish things
#endif #endif
#if IFAN_SUPPORT
#undef RELAY_SUPPORT
#define RELAY_SUPPORT 1 // Need relays to manage general state
#endif
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
// Hint about ESPAsyncTCP options and our internal one // Hint about ESPAsyncTCP options and our internal one
// TODO: clean-up SSL_ENABLED and USE_SSL settings for 1.15.0 // TODO: clean-up SSL_ENABLED and USE_SSL settings for 1.15.0


+ 1
- 4
code/espurna/config/hardware.h View File

@ -1014,7 +1014,7 @@
#define IFAN_SUPPORT 1 #define IFAN_SUPPORT 1
// These buttons are triggered by the remote // These buttons are triggered by the remote
// iFan module adds a custom button handler
// iFan module adds a custom button handler and a special relay controlling the speed
#define BUTTON1_PIN 0 #define BUTTON1_PIN 0
#define BUTTON1_CLICK BUTTON_ACTION_TOGGLE #define BUTTON1_CLICK BUTTON_ACTION_TOGGLE
@ -1027,9 +1027,6 @@
#define BUTTON4_PIN 14 #define BUTTON4_PIN 14
#define BUTTON4_CLICK BUTTON_ACTION_CUSTOM #define BUTTON4_CLICK BUTTON_ACTION_CUSTOM
// Only one relay by default, controlling the ON / OFF
#define RELAY1_PIN 12
// LEDs // LEDs
#define LED1_PIN 13 #define LED1_PIN 13
#define LED1_PIN_INVERSE 1 #define LED1_PIN_INVERSE 1


+ 89
- 46
code/espurna/ifan.cpp View File

@ -99,8 +99,6 @@ constexpr unsigned long DefaultSaveDelay { 1000ul };
// Remote presses trigger GPIO pushbutton events // Remote presses trigger GPIO pushbutton events
// Attach to a specific ID to trigger an action // Attach to a specific ID to trigger an action
constexpr unsigned char DefaultRelayId { 0u };
constexpr unsigned char DefaultLowButtonId { 1u }; constexpr unsigned char DefaultLowButtonId { 1u };
constexpr unsigned char DefaultMediumButtonId { 2u }; constexpr unsigned char DefaultMediumButtonId { 2u };
constexpr unsigned char DefaultHighButtonId { 3u }; constexpr unsigned char DefaultHighButtonId { 3u };
@ -125,9 +123,22 @@ StatePins statePins() {
}; };
} }
constexpr int controlPin() {
return 12;
}
struct Config { struct Config {
Config() = default;
explicit Config(unsigned long save_, unsigned char buttonLowId_,
unsigned char buttonMediumId_, unsigned char buttonHighId_, Speed speed_) :
save(save_),
buttonLowId(buttonLowId_),
buttonMediumId(buttonMediumId_),
buttonHighId(buttonHighId_),
speed(speed_)
{}
unsigned long save { DefaultSaveDelay }; unsigned long save { DefaultSaveDelay };
unsigned char relayId { DefaultRelayId };
unsigned char buttonLowId { DefaultLowButtonId }; unsigned char buttonLowId { DefaultLowButtonId };
unsigned char buttonMediumId { DefaultMediumButtonId }; unsigned char buttonMediumId { DefaultMediumButtonId };
unsigned char buttonHighId { DefaultHighButtonId }; unsigned char buttonHighId { DefaultHighButtonId };
@ -136,14 +147,13 @@ struct Config {
}; };
Config readSettings() { Config readSettings() {
return {
return Config(
getSetting("ifanSave", DefaultSaveDelay), getSetting("ifanSave", DefaultSaveDelay),
getSetting("ifanRelayId", DefaultRelayId),
getSetting("ifanBtnLowId", DefaultLowButtonId), getSetting("ifanBtnLowId", DefaultLowButtonId),
getSetting("ifanBtnLowId", DefaultMediumButtonId),
getSetting("ifanBtnMediumId", DefaultMediumButtonId),
getSetting("ifanBtnHighId", DefaultHighButtonId), getSetting("ifanBtnHighId", DefaultHighButtonId),
getSetting("ifanSpeed", Speed::Medium) getSetting("ifanSpeed", Speed::Medium)
};
);
} }
Config config; Config config;
@ -223,41 +233,38 @@ const char* maskFromSpeed(Speed speed) {
return ""; return "";
} }
void setSpeed(StatePins& pins, Speed speed) {
auto state = stateFromSpeed(speed);
DEBUG_MSG_P(PSTR("[IFAN] State mask: %s\n"), maskFromSpeed(speed));
for (size_t index = 0; index < pins.size(); ++ index) {
if (!pins[index].second) continue;
pins[index].second->digitalWrite(state[index]);
}
}
void setSpeed(Speed speed) {
setSpeed(config.state_pins, speed);
}
// Note that we use API speed endpoint strictly for the setting // Note that we use API speed endpoint strictly for the setting
// (which also allows to pre-set the speed without turning the relay ON) // (which also allows to pre-set the speed without turning the relay ON)
void setSpeedFromPayload(const char* payload) {
auto speed = payloadToSpeed(payload);
using FanSpeedUpdate = std::function<void(Speed)>;
FanSpeedUpdate onSpeedUpdate = [](Speed) {
};
void updateSpeed(Config& config, Speed speed) {
switch (speed) { switch (speed) {
case Speed::Low: case Speed::Low:
case Speed::Medium: case Speed::Medium:
case Speed::High: case Speed::High:
setSpeed(speed);
report(speed);
save(speed); save(speed);
report(speed);
onSpeedUpdate(speed);
break; break;
case Speed::Off: case Speed::Off:
break; break;
} }
} }
void setSpeedFromPayload(const String& payload) {
setSpeedFromPayload(payload.c_str());
void updateSpeed(Speed speed) {
updateSpeed(config, speed);
}
void updateSpeedFromPayload(const char* payload) {
updateSpeed(payloadToSpeed(payload));
}
void updateSpeedFromPayload(const String& payload) {
updateSpeedFromPayload(payload.c_str());
} }
#if MQTT_SUPPORT #if MQTT_SUPPORT
@ -272,7 +279,7 @@ void onMqttEvent(unsigned int type, const char* topic, const char* payload) {
case MQTT_MESSAGE_EVENT: { case MQTT_MESSAGE_EVENT: {
auto parsed = mqttMagnitude(topic); auto parsed = mqttMagnitude(topic);
if (parsed.startsWith(MQTT_TOPIC_SPEED)) { if (parsed.startsWith(MQTT_TOPIC_SPEED)) {
setSpeedFromPayload(payload);
updateSpeedFromPayload(payload);
} }
break; break;
} }
@ -282,9 +289,45 @@ void onMqttEvent(unsigned int type, const char* topic, const char* payload) {
#endif // MQTT_SUPPORT #endif // MQTT_SUPPORT
void setSpeedFromStatus(bool status) {
setSpeed(status ? config.speed : Speed::Off);
}
class FanProvider : public RelayProviderBase {
public:
explicit FanProvider(BasePinPtr&& pin, const Config& config, FanSpeedUpdate& callback) :
_pin(std::move(pin)),
_config(config)
{
callback = [this](Speed speed) {
change(speed);
};
}
const char* id() const override {
return "fan";
}
void change(Speed speed) {
_pin->digitalWrite((Speed::Off != speed) ? HIGH : LOW);
auto state = stateFromSpeed(speed);
DEBUG_MSG_P(PSTR("[IFAN] State mask: %s\n"), maskFromSpeed(speed));
for (size_t index = 0; index < _config.state_pins.size(); ++index) {
auto& pin = _config.state_pins[index].second;
if (!pin) {
continue;
}
pin->digitalWrite(state[index]);
}
}
void change(bool status) override {
change(status ? _config.speed : Speed::Off);
}
private:
BasePinPtr _pin;
const Config& _config;
};
void setup() { void setup() {
@ -297,23 +340,23 @@ void setup() {
espurnaRegisterReload(configure); espurnaRegisterReload(configure);
auto relay_pin = gpioRegister(controlPin());
if (relay_pin) {
auto provider = std::make_unique<FanProvider>(std::move(relay_pin), config, onSpeedUpdate);
if (!relayAdd(std::move(provider))) {
DEBUG_MSG_P(PSTR("[IFAN] Could not add relay provider for GPIO%d\n"), relay_pin->pin());
gpioUnlock(relay_pin->pin());
}
}
#if BUTTON_SUPPORT #if BUTTON_SUPPORT
buttonSetCustomAction([](unsigned char id) { buttonSetCustomAction([](unsigned char id) {
if (config.buttonLowId == id) { if (config.buttonLowId == id) {
setSpeed(Speed::Low);
updateSpeed(Speed::Low);
} else if (config.buttonMediumId == id) { } else if (config.buttonMediumId == id) {
setSpeed(Speed::Medium);
updateSpeed(Speed::Medium);
} else if (config.buttonHighId == id) { } else if (config.buttonHighId == id) {
setSpeed(Speed::High);
}
});
#endif
#if RELAY_SUPPORT
setSpeedFromStatus(relayStatus(config.relayId));
relaySetStatusChange([](unsigned char id, bool status) {
if (config.relayId == id) {
setSpeedFromStatus(status);
updateSpeed(Speed::High);
} }
}); });
#endif #endif
@ -329,7 +372,7 @@ void setup() {
return true; return true;
}, },
[](ApiRequest& request) { [](ApiRequest& request) {
setSpeedFromPayload(request.param(F("value")));
updateSpeedFromPayload(request.param(F("value")));
return true; return true;
} }
); );
@ -338,7 +381,7 @@ void setup() {
#if TERMINAL_SUPPORT #if TERMINAL_SUPPORT
terminalRegisterCommand(F("SPEED"), [](const terminal::CommandContext& ctx) { terminalRegisterCommand(F("SPEED"), [](const terminal::CommandContext& ctx) {
if (ctx.argc == 2) { if (ctx.argc == 2) {
setSpeedFromPayload(ctx.argv[1]);
updateSpeedFromPayload(ctx.argv[1]);
} }
ctx.output.println(speedToPayload(config.speed)); ctx.output.println(speedToPayload(config.speed));


Loading…
Cancel
Save