@ -14,7 +14,7 @@ Copyright (C) 2016-2019 by Xose Pérez <xose dot perez at gmail dot com>
# if IFAN_SUPPORT
# if IFAN_SUPPORT
# include "api.h"
# include "api.h"
# include "butto n.h"
# include "fa n.h"
# include "mqtt.h"
# include "mqtt.h"
# include "relay.h"
# include "relay.h"
# include "terminal.h"
# include "terminal.h"
@ -22,60 +22,55 @@ Copyright (C) 2016-2019 by Xose Pérez <xose dot perez at gmail dot com>
# include <array>
# include <array>
# include <utility>
# include <utility>
namespace ifan02 {
// TODO: in case there are more FANs, move externally
enum class Speed {
Off ,
Low ,
Medium ,
High
} ;
namespace ifan02 {
const char * speedToPayload ( Speed value ) {
const char * speedToPayload ( FanSpeed value ) {
switch ( value ) {
switch ( value ) {
case Speed : : Off :
case FanSpeed : : Off :
return " off " ;
return " off " ;
case Speed : : Low :
case Fan Speed: : Low :
return " low " ;
return " low " ;
case Speed : : Medium :
case Fan Speed: : Medium :
return " medium " ;
return " medium " ;
case Speed : : High :
case Fan Speed: : High :
return " high " ;
return " high " ;
}
}
return " " ;
return " " ;
}
}
Speed payloadToSpeed ( const char * payload ) {
Fan Speed payloadToSpeed ( const char * payload ) {
auto len = strlen ( payload ) ;
auto len = strlen ( payload ) ;
if ( len = = 1 ) {
if ( len = = 1 ) {
switch ( payload [ 0 ] ) {
switch ( payload [ 0 ] ) {
case ' 0 ' :
case ' 0 ' :
return Speed : : Off ;
return Fan Speed: : Off ;
case ' 1 ' :
case ' 1 ' :
return Speed : : Low ;
return Fan Speed: : Low ;
case ' 2 ' :
case ' 2 ' :
return Speed : : Medium ;
return Fan Speed: : Medium ;
case ' 3 ' :
case ' 3 ' :
return Speed : : High ;
return Fan Speed: : High ;
}
}
} else if ( len > 1 ) {
} else if ( len > 1 ) {
String cmp ( payload ) ;
String cmp ( payload ) ;
if ( cmp = = " off " ) {
if ( cmp = = " off " ) {
return Speed : : Off ;
return Fan Speed: : Off ;
} else if ( cmp = = " low " ) {
} else if ( cmp = = " low " ) {
return Speed : : Low ;
return Fan Speed: : Low ;
} else if ( cmp = = " medium " ) {
} else if ( cmp = = " medium " ) {
return Speed : : Medium ;
return Fan Speed: : Medium ;
} else if ( cmp = = " high " ) {
} else if ( cmp = = " high " ) {
return Speed : : High ;
return Fan Speed: : High ;
}
}
}
}
return Speed : : Off ;
return Fan Speed: : Off ;
}
}
Speed payloadToSpeed ( const String & string ) {
Fan Speed payloadToSpeed ( const String & string ) {
return payloadToSpeed ( string . c_str ( ) ) ;
return payloadToSpeed ( string . c_str ( ) ) ;
}
}
@ -85,7 +80,7 @@ namespace settings {
namespace internal {
namespace internal {
template < >
template < >
ifan02 : : Speed convert ( const String & value ) {
FanSpeed convert ( const String & value ) {
return ifan02 : : payloadToSpeed ( value ) ;
return ifan02 : : payloadToSpeed ( value ) ;
}
}
@ -96,13 +91,6 @@ namespace ifan02 {
constexpr unsigned long DefaultSaveDelay { 1000ul } ;
constexpr unsigned long DefaultSaveDelay { 1000ul } ;
// Remote presses trigger GPIO pushbutton events
// Attach to a specific ID to trigger an action
constexpr unsigned char DefaultLowButtonId { 1u } ;
constexpr unsigned char DefaultMediumButtonId { 2u } ;
constexpr unsigned char DefaultHighButtonId { 3u } ;
// We expect to write a specific 'mask' via GPIO LOW & HIGH to set the speed
// We expect to write a specific 'mask' via GPIO LOW & HIGH to set the speed
// Sync up with the relay and write it on ON / OFF status events
// Sync up with the relay and write it on ON / OFF status events
@ -129,30 +117,20 @@ constexpr int controlPin() {
struct Config {
struct Config {
Config ( ) = default ;
Config ( ) = default ;
explicit Config ( unsigned long save_ , unsigned char buttonLowId_ ,
unsigned char buttonMediumId_ , unsigned char buttonHighId_ , Speed speed_ ) :
explicit Config ( unsigned long save_ , FanSpeed speed_ ) :
save ( save_ ) ,
save ( save_ ) ,
buttonLowId ( buttonLowId_ ) ,
buttonMediumId ( buttonMediumId_ ) ,
buttonHighId ( buttonHighId_ ) ,
speed ( speed_ )
speed ( speed_ )
{ }
{ }
unsigned long save { DefaultSaveDelay } ;
unsigned long save { DefaultSaveDelay } ;
unsigned char buttonLowId { DefaultLowButtonId } ;
unsigned char buttonMediumId { DefaultMediumButtonId } ;
unsigned char buttonHighId { DefaultHighButtonId } ;
Speed speed { Speed : : Off } ;
FanSpeed speed { FanSpeed : : Off } ;
StatePins state_pins ;
StatePins state_pins ;
} ;
} ;
Config readSettings ( ) {
Config readSettings ( ) {
return Config (
return Config (
getSetting ( " ifanSave " , DefaultSaveDelay ) ,
getSetting ( " ifanBtnLowId " , DefaultLowButtonId ) ,
getSetting ( " ifanBtnMediumId " , DefaultMediumButtonId ) ,
getSetting ( " ifanBtnHighId " , DefaultHighButtonId ) ,
getSetting ( " ifanSpeed " , Speed : : Medium )
getSetting ( " fanSave " , DefaultSaveDelay ) ,
getSetting ( " fanSpeed " , FanSpeed : : Medium )
) ;
) ;
}
}
@ -162,18 +140,18 @@ void configure() {
config = readSettings ( ) ;
config = readSettings ( ) ;
}
}
void report ( Speed speed [[gnu::unused]] ) {
void report ( Fan Speed speed [[gnu::unused]] ) {
# if MQTT_SUPPORT
# if MQTT_SUPPORT
mqttSend ( MQTT_TOPIC_SPEED , speedToPayload ( speed ) ) ;
mqttSend ( MQTT_TOPIC_SPEED , speedToPayload ( speed ) ) ;
# endif
# endif
}
}
void save ( Speed speed ) {
void save ( Fan Speed speed ) {
static Ticker ticker ;
static Ticker ticker ;
config . speed = speed ;
config . speed = speed ;
ticker . once_ms ( config . save , [ ] ( ) {
ticker . once_ms ( config . save , [ ] ( ) {
const char * value = speedToPayload ( config . speed ) ;
const char * value = speedToPayload ( config . speed ) ;
setSetting ( " i fanSpeed" , value ) ;
setSetting ( " fanSpeed " , value ) ;
DEBUG_MSG_P ( PSTR ( " [IFAN] Saved speed setting \" %s \" \n " ) , value ) ;
DEBUG_MSG_P ( PSTR ( " [IFAN] Saved speed setting \" %s \" \n " ) , value ) ;
} ) ;
} ) ;
}
}
@ -203,30 +181,30 @@ StatePins setupStatePins() {
return pins ;
return pins ;
}
}
State stateFromSpeed ( Speed speed ) {
State stateFromSpeed ( Fan Speed speed ) {
switch ( speed ) {
switch ( speed ) {
case Speed : : Low :
case Fan Speed: : Low :
return { HIGH , LOW , LOW } ;
return { HIGH , LOW , LOW } ;
case Speed : : Medium :
case Fan Speed: : Medium :
return { HIGH , HIGH , LOW } ;
return { HIGH , HIGH , LOW } ;
case Speed : : High :
case Fan Speed: : High :
return { HIGH , LOW , HIGH } ;
return { HIGH , LOW , HIGH } ;
case Speed : : Off :
case Fan Speed: : Off :
break ;
break ;
}
}
return { LOW , LOW , LOW } ;
return { LOW , LOW , LOW } ;
}
}
const char * maskFromSpeed ( Speed speed ) {
const char * maskFromSpeed ( Fan Speed speed ) {
switch ( speed ) {
switch ( speed ) {
case Speed : : Low :
case Fan Speed: : Low :
return " 0b100 " ;
return " 0b100 " ;
case Speed : : Medium :
case Fan Speed: : Medium :
return " 0b110 " ;
return " 0b110 " ;
case Speed : : High :
case Fan Speed: : High :
return " 0b101 " ;
return " 0b101 " ;
case Speed : : Off :
case Fan Speed: : Off :
return " 0b000 " ;
return " 0b000 " ;
}
}
@ -236,26 +214,26 @@ const char* maskFromSpeed(Speed 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)
using FanSpeedUpdate = std : : function < void ( Speed ) > ;
using FanSpeedUpdate = std : : function < void ( Fan Speed) > ;
FanSpeedUpdate onSpeedUpdate = [ ] ( Speed ) {
FanSpeedUpdate onFan SpeedUpdate = [ ] ( Fan Speed) {
} ;
} ;
void updateSpeed ( Config & config , Speed speed ) {
void updateSpeed ( Config & config , Fan Speed speed ) {
switch ( speed ) {
switch ( speed ) {
case Speed : : Low :
case Speed : : Medium :
case Speed : : High :
case Fan Speed: : Low :
case Fan Speed: : Medium :
case Fan Speed: : High :
save ( speed ) ;
save ( speed ) ;
report ( speed ) ;
report ( speed ) ;
onSpeedUpdate ( speed ) ;
onFan SpeedUpdate ( speed ) ;
break ;
break ;
case Speed : : Off :
case Fan Speed: : Off :
break ;
break ;
}
}
}
}
void updateSpeed ( Speed speed ) {
void updateSpeed ( Fan Speed speed ) {
updateSpeed ( config , speed ) ;
updateSpeed ( config , speed ) ;
}
}
@ -295,17 +273,18 @@ public:
_pin ( std : : move ( pin ) ) ,
_pin ( std : : move ( pin ) ) ,
_config ( config )
_config ( config )
{
{
callback = [ this ] ( Speed speed ) {
callback = [ this ] ( Fan Speed speed ) {
change ( speed ) ;
change ( speed ) ;
} ;
} ;
_pin - > pinMode ( OUTPUT ) ;
}
}
const char * id ( ) const override {
const char * id ( ) const override {
return " fan " ;
return " fan " ;
}
}
void change ( Speed speed ) {
_pin - > digitalWrite ( ( Speed : : Off ! = speed ) ? HIGH : LOW ) ;
void change ( Fan Speed speed ) {
_pin - > digitalWrite ( ( Fan Speed: : Off ! = speed ) ? HIGH : LOW ) ;
auto state = stateFromSpeed ( speed ) ;
auto state = stateFromSpeed ( speed ) ;
DEBUG_MSG_P ( PSTR ( " [IFAN] State mask: %s \n " ) , maskFromSpeed ( speed ) ) ;
DEBUG_MSG_P ( PSTR ( " [IFAN] State mask: %s \n " ) , maskFromSpeed ( speed ) ) ;
@ -321,7 +300,7 @@ public:
}
}
void change ( bool status ) override {
void change ( bool status ) override {
change ( status ? _config . speed : Speed : : Off ) ;
change ( status ? _config . speed : Fan Speed: : Off ) ;
}
}
private :
private :
@ -342,26 +321,13 @@ void setup() {
auto relay_pin = gpioRegister ( controlPin ( ) ) ;
auto relay_pin = gpioRegister ( controlPin ( ) ) ;
if ( relay_pin ) {
if ( relay_pin ) {
relay_pin - > pinMode ( OUTPUT ) ;
auto provider = std : : make_unique < FanProvider > ( std : : move ( relay_pin ) , config , onSpeedUpdate ) ;
auto provider = std : : make_unique < FanProvider > ( std : : move ( relay_pin ) , config , onFanSpeedUpdate ) ;
if ( ! relayAdd ( std : : move ( provider ) ) ) {
if ( ! relayAdd ( std : : move ( provider ) ) ) {
DEBUG_MSG_P ( PSTR ( " [IFAN] Could not add relay provider for GPIO%d \n " ) , controlPin ( ) ) ;
DEBUG_MSG_P ( PSTR ( " [IFAN] Could not add relay provider for GPIO%d \n " ) , controlPin ( ) ) ;
gpioUnlock ( controlPin ( ) ) ;
gpioUnlock ( controlPin ( ) ) ;
}
}
}
}
# if BUTTON_SUPPORT
buttonSetCustomAction ( [ ] ( unsigned char id ) {
if ( config . buttonLowId = = id ) {
updateSpeed ( Speed : : Low ) ;
} else if ( config . buttonMediumId = = id ) {
updateSpeed ( Speed : : Medium ) ;
} else if ( config . buttonHighId = = id ) {
updateSpeed ( Speed : : High ) ;
}
} ) ;
# endif
# if MQTT_SUPPORT
# if MQTT_SUPPORT
mqttRegister ( onMqttEvent ) ;
mqttRegister ( onMqttEvent ) ;
# endif
# endif
@ -394,7 +360,15 @@ void setup() {
} // namespace ifan
} // namespace ifan
void ifanSetup ( ) {
FanSpeed fanSpeed ( ) {
return ifan02 : : config . speed ;
}
void fanSpeed ( FanSpeed speed ) {
ifan02 : : updateSpeed ( FanSpeed : : Low ) ;
}
void fanSetup ( ) {
ifan02 : : setup ( ) ;
ifan02 : : setup ( ) ;
}
}