implement gpio output via mqtt
This commit is contained in:
13
Gpio.cpp
13
Gpio.cpp
@@ -151,6 +151,18 @@ const std::vector<PinEntry> &Gpio::pinConfiguration() const
|
||||
return _pinConfiguration;
|
||||
}
|
||||
|
||||
const PinRole Gpio::getPinRole(const int &pin) const
|
||||
{
|
||||
for(const auto& pinEntry : _pinConfiguration)
|
||||
{
|
||||
if(pinEntry.pin == pin)
|
||||
{
|
||||
return pinEntry.role;
|
||||
}
|
||||
}
|
||||
return PinRole::Disabled;
|
||||
}
|
||||
|
||||
String Gpio::getRoleDescription(PinRole role) const
|
||||
{
|
||||
switch(role)
|
||||
@@ -315,3 +327,4 @@ void Gpio::migrateObsoleteSetting()
|
||||
delay(200);
|
||||
restartEsp(RestartReason::GpioConfigurationUpdated);
|
||||
}
|
||||
|
||||
|
||||
1
Gpio.h
1
Gpio.h
@@ -57,6 +57,7 @@ public:
|
||||
|
||||
const std::vector<uint8_t>& availablePins() const;
|
||||
const std::vector<PinEntry>& pinConfiguration() const;
|
||||
const PinRole getPinRole(const int& pin) const;
|
||||
|
||||
String getRoleDescription(PinRole role) const;
|
||||
void getConfigurationText(String& text, const std::vector<PinEntry>& pinConfiguration, const String& linebreak = "\n") const;
|
||||
|
||||
@@ -63,4 +63,6 @@
|
||||
#define mqtt_topic_network_device "/maintenance/networkDevice"
|
||||
|
||||
#define mqtt_topic_gpio_prefix "/gpio"
|
||||
#define mqtt_topic_gpio_input "/input_"
|
||||
#define mqtt_topic_gpio_pin "/pin_"
|
||||
#define mqtt_topic_gpio_role "/role"
|
||||
#define mqtt_topic_gpio_state "/state"
|
||||
|
||||
79
Network.cpp
79
Network.cpp
@@ -213,21 +213,36 @@ void Network::initialize()
|
||||
|
||||
_publishDebugInfo = _preferences->getBool(preference_publish_debug_info);
|
||||
|
||||
char gpioPath[200];
|
||||
char gpioPath[250];
|
||||
bool rebGpio = rebuildGpio();
|
||||
|
||||
for(const auto& pinEntry : _gpio->pinConfiguration())
|
||||
if(rebGpio)
|
||||
{
|
||||
switch(pinEntry.role)
|
||||
Log->println(F("Rebuild MQTT GPIO structure"));
|
||||
}
|
||||
for (const auto &pinEntry: _gpio->pinConfiguration())
|
||||
{
|
||||
switch (pinEntry.role)
|
||||
{
|
||||
case PinRole::GeneralInput:
|
||||
memset(gpioPath, 0, sizeof(gpioPath));
|
||||
buildMqttPath(gpioPath, {mqtt_topic_gpio_prefix, (mqtt_topic_gpio_input + std::to_string(pinEntry.pin)).c_str(), "role" });
|
||||
publishString(_lockPath.c_str(), gpioPath, "input");
|
||||
if(rebGpio)
|
||||
{
|
||||
buildMqttPath(gpioPath, {mqtt_topic_gpio_prefix, (mqtt_topic_gpio_pin + std::to_string(pinEntry.pin)).c_str(), mqtt_topic_gpio_role});
|
||||
publishString(_lockPath.c_str(), gpioPath, "input");
|
||||
buildMqttPath(gpioPath, {mqtt_topic_gpio_prefix, (mqtt_topic_gpio_pin + std::to_string(pinEntry.pin)).c_str(), mqtt_topic_gpio_state});
|
||||
publishString(_lockPath.c_str(), gpioPath, std::to_string(digitalRead(pinEntry.pin)).c_str());
|
||||
}
|
||||
break;
|
||||
case PinRole::GeneralOutput:
|
||||
memset(gpioPath, 0, sizeof(gpioPath));
|
||||
buildMqttPath(gpioPath, {mqtt_topic_gpio_prefix, (mqtt_topic_gpio_input + std::to_string(pinEntry.pin)).c_str(), "role" });
|
||||
publishString(_lockPath.c_str(), gpioPath, "output");
|
||||
if(rebGpio)
|
||||
{
|
||||
buildMqttPath(gpioPath, {mqtt_topic_gpio_prefix, (mqtt_topic_gpio_pin + std::to_string(pinEntry.pin)).c_str(), mqtt_topic_gpio_role});
|
||||
publishString(_lockPath.c_str(), gpioPath, "output");
|
||||
buildMqttPath(gpioPath, {mqtt_topic_gpio_prefix, (mqtt_topic_gpio_pin + std::to_string(pinEntry.pin)).c_str(), mqtt_topic_gpio_state});
|
||||
publishString(_lockPath.c_str(), gpioPath, "0");
|
||||
}
|
||||
buildMqttPath(gpioPath, {mqtt_topic_gpio_prefix, (mqtt_topic_gpio_pin + std::to_string(pinEntry.pin)).c_str(), mqtt_topic_gpio_state});
|
||||
subscribe(_lockPath.c_str(), gpioPath);
|
||||
break;
|
||||
}
|
||||
}
|
||||
@@ -509,11 +524,6 @@ void Network::registerMqttReceiver(MqttReceiver* receiver)
|
||||
|
||||
void Network::onMqttDataReceivedCallback(const espMqttClientTypes::MessageProperties& properties, const char* topic, const uint8_t* payload, size_t len, size_t index, size_t total)
|
||||
{
|
||||
if(millis() < _ignoreSubscriptionsTs)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
uint8_t value[50] = {0};
|
||||
size_t l = min(len, sizeof(value)-1);
|
||||
|
||||
@@ -525,14 +535,53 @@ void Network::onMqttDataReceivedCallback(const espMqttClientTypes::MessageProper
|
||||
_inst->onMqttDataReceived(properties, topic, value, len, index, total);
|
||||
}
|
||||
|
||||
void Network::onMqttDataReceived(const espMqttClientTypes::MessageProperties& properties, const char* topic, const uint8_t* payload, size_t len, size_t index, size_t total)
|
||||
void Network::onMqttDataReceived(const espMqttClientTypes::MessageProperties& properties, const char* topic, const uint8_t* payload, size_t& len, size_t& index, size_t& total)
|
||||
{
|
||||
parseGpioTopics(properties, topic, payload, len, index, total);
|
||||
|
||||
if(millis() < _ignoreSubscriptionsTs)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
for(auto receiver : _mqttReceivers)
|
||||
{
|
||||
receiver->onMqttDataReceived(topic, (byte*)payload, index);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void Network::parseGpioTopics(const espMqttClientTypes::MessageProperties &properties, const char *topic, const uint8_t *payload, size_t& len, size_t& index, size_t& total)
|
||||
{
|
||||
char gpioPath[250];
|
||||
buildMqttPath(gpioPath, {_lockPath.c_str(), mqtt_topic_gpio_prefix, mqtt_topic_gpio_pin});
|
||||
// /nuki_t/gpio/pin_17/state
|
||||
size_t gpioLen = strlen(gpioPath);
|
||||
if(strncmp(gpioPath, topic, gpioLen) == 0)
|
||||
{
|
||||
char pinStr[3] = {0};
|
||||
pinStr[0] = topic[gpioLen];
|
||||
if(topic[gpioLen+1] != '/')
|
||||
{
|
||||
pinStr[1] = topic[gpioLen+1];
|
||||
}
|
||||
|
||||
int pin = std::atoi(pinStr);
|
||||
|
||||
if(_gpio->getPinRole(pin) == PinRole::GeneralOutput)
|
||||
{
|
||||
const uint8_t pinState = strcmp((const char*)payload, "1") == 0 ? HIGH : LOW;
|
||||
Log->print(F("GPIO "));
|
||||
Log->print(pin);
|
||||
Log->print(F(" (Output) --> "));
|
||||
Log->println(pinState);
|
||||
digitalWrite(pin, pinState);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void Network::reconfigureDevice()
|
||||
{
|
||||
_device->reconfigure();
|
||||
|
||||
@@ -75,7 +75,8 @@ public:
|
||||
|
||||
private:
|
||||
static void onMqttDataReceivedCallback(const espMqttClientTypes::MessageProperties& properties, const char* topic, const uint8_t* payload, size_t len, size_t index, size_t total);
|
||||
void onMqttDataReceived(const espMqttClientTypes::MessageProperties& properties, const char* topic, const uint8_t* payload, size_t len, size_t index, size_t total);
|
||||
void onMqttDataReceived(const espMqttClientTypes::MessageProperties& properties, const char* topic, const uint8_t* payload, size_t& len, size_t& index, size_t& total);
|
||||
void parseGpioTopics(const espMqttClientTypes::MessageProperties& properties, const char* topic, const uint8_t* payload, size_t& len, size_t& index, size_t& total);
|
||||
void setupDevice();
|
||||
bool reconnect();
|
||||
|
||||
|
||||
@@ -25,24 +25,37 @@ enum class RestartReason
|
||||
#define RESTART_REASON_VALID_DETECT 0xa00ab00bc00bd00d;
|
||||
|
||||
extern int restartReason;
|
||||
extern uint64_t restartReasonValid;
|
||||
extern uint64_t restartReasonValidDetect;
|
||||
extern bool rebuildGpioRequested;
|
||||
|
||||
extern RestartReason currentRestartReason;
|
||||
|
||||
extern bool restartReason_isValid;
|
||||
|
||||
|
||||
inline static void restartEsp(RestartReason reason)
|
||||
{
|
||||
if(reason == RestartReason::GpioConfigurationUpdated)
|
||||
{
|
||||
rebuildGpioRequested = true;
|
||||
}
|
||||
restartReason = (int)reason;
|
||||
restartReasonValid = RESTART_REASON_VALID_DETECT;
|
||||
restartReasonValidDetect = RESTART_REASON_VALID_DETECT;
|
||||
ESP.restart();
|
||||
}
|
||||
|
||||
inline static void initializeRestartReason()
|
||||
{
|
||||
uint64_t cmp = RESTART_REASON_VALID_DETECT;
|
||||
if(restartReasonValid == cmp)
|
||||
restartReason_isValid = (restartReasonValidDetect == cmp);
|
||||
if(restartReason_isValid)
|
||||
{
|
||||
currentRestartReason = (RestartReason)restartReason;
|
||||
memset(&restartReasonValid, 0, sizeof(restartReasonValid));
|
||||
memset(&restartReasonValidDetect, 0, sizeof(restartReasonValidDetect));
|
||||
}
|
||||
else
|
||||
{
|
||||
rebuildGpioRequested = false;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -121,4 +134,11 @@ inline static String getEspRestartReason()
|
||||
default:
|
||||
return "Unknown: " + (int)reason;
|
||||
}
|
||||
}
|
||||
|
||||
inline bool rebuildGpio()
|
||||
{
|
||||
bool rebGpio = rebuildGpioRequested;
|
||||
rebuildGpioRequested = false;
|
||||
return restartReason_isValid && rebGpio;
|
||||
}
|
||||
4
main.cpp
4
main.cpp
@@ -34,7 +34,9 @@ bool openerEnabled = false;
|
||||
unsigned long restartTs = (2^32) - 5 * 60000;
|
||||
|
||||
RTC_NOINIT_ATTR int restartReason;
|
||||
RTC_NOINIT_ATTR uint64_t restartReasonValid;
|
||||
RTC_NOINIT_ATTR uint64_t restartReasonValidDetect;
|
||||
RTC_NOINIT_ATTR bool rebuildGpioRequested;
|
||||
bool restartReason_isValid;
|
||||
RestartReason currentRestartReason = RestartReason::NotApplicable;
|
||||
|
||||
TaskHandle_t networkTaskHandle = nullptr;
|
||||
|
||||
Reference in New Issue
Block a user