Skip to content

Instantly share code, notes, and snippets.

@davea
Created February 18, 2020 19:42
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save davea/466d42d62e3ff32fd0e5dc16d7d525d0 to your computer and use it in GitHub Desktop.
Save davea/466d42d62e3ff32fd0e5dc16d7d525d0 to your computer and use it in GitHub Desktop.

HomeKitSwitchComponent

This component allows you to publish a custom payload to a custom topic(s) for an ESPHome switch component.

This makes it easier to integrate with HomeKit which expects a 0 or 1 instead of ON/OFF for switches.

Example configuration for publishing a relay's state as 0 or 1 to a custom topic which is compatible with mqtt2homekit (more info):

esphome:
  includes:
    - homekit_switch.h

switch:
  - platform: gpio
    name: "Sonoff Basic Relay"
    pin: GPIO12
    id: relay


custom_component:
    - lambda: |-
        auto my_component = new mqtt::HomeKitSwitchComponent(relay);
        App.register_component(my_component);
        my_component->set_custom_state_topic("HomeKit/sonoffbasic/Switch/On");
        my_component->set_custom_command_topic("HomeKit/sonoffbasic/Switch/On");
        return {my_component};
#include "esphome.h"
namespace esphome {
namespace mqtt {
using namespace esphome::switch_;
static const char *TAG = "homekit.switch";
static const char *ON = "1";
static const char *OFF = "0";
class HomeKitSwitchComponent : public mqtt::MQTTSwitchComponent {
public:
HomeKitSwitchComponent(switch_::Switch *a_switch) : MQTTSwitchComponent(a_switch) {}
void setup() override {
this->subscribe(this->get_command_topic_(), [this](const std::string &topic, const std::string &payload) {
switch (parse_on_off(payload.c_str(), ON, OFF)) {
case PARSE_ON:
this->switch_->turn_on();
break;
case PARSE_OFF:
this->switch_->turn_off();
break;
case PARSE_TOGGLE:
this->switch_->toggle();
break;
case PARSE_NONE:
default:
ESP_LOGW(TAG, "'%s': Received unknown status payload: %s", this->friendly_name().c_str(), payload.c_str());
this->status_momentary_warning("state", 5000);
break;
}
});
this->switch_->add_on_state_callback(
[this](bool enabled) { this->defer("send", [this, enabled]() { this->publish_state(enabled); }); });
}
// We need to override this otherwise the parent class method will call publish_state
// on the parent class instead of ours, meaning the initial state message will be
// "ON" or "OFF" not "0"/"1"
bool send_initial_state() override { return this->publish_state(this->switch_->state); }
bool publish_state(bool state) {
const char *state_s = state ? ON : OFF;
return this->publish(this->get_state_topic_(), state_s);
}
};
} // namespace mqtt
} // namespace esphome
@paulsteigel
Copy link

Thank you for your post, I found it nearly similar to my case but I am struggling with it. Can you please be so kind to guide me on how to integrate ESPHOME Mqtt with Thingsboard.io.

My requirement:
I have a device running on ESPhome and control gpio via pcf8574, code below. I would like this to be controllable on thingsboard.io via MQTT but I dont know how to integrate gpio switch with mqtt. A lot of tries and errors with no luck. My code as below but thingsboard does not receive any information from the device:

mqtt:
  broker: "104.196.24.70"
  client_id: "ik5gju7poo2s5ko52u5j"
  username: "paulsteigel"
  password: "D1ndh1sk@"
  discovery: false
  port: 1883
  on_connect:
    - mqtt.publish_json:
        topic: v1/devices/me/attributes
        payload: !lambda |-          
          root["pin"] = "id7";
          root["enabled"] = id(id7).state;  

switch:
  - platform: gpio
    name: "Home lamp"
    id: id7
    pin:
      pcf8574: pcf8574_hub
      # Use pin number P7
      number: 7
      # One of INPUT or OUTPUT
      mode: 
        output: true
      inverted: false
    state_topic: 'v1/devices/me/attributes'
    command_topic: 'v1/devices/me/attributes/getGpioStatus'
    on_turn_on:
      then:
      - mqtt.publish_json:
          topic: "v1/devices/me/attributes" 
          retain: true
          payload: !lambda |-
            root["pin"] = "id7";
            root["enabled"] = id(id7).state;
    on_turn_off:
      then:
      - mqtt.publish_json:
          topic: "v1/devices/me/attributes" 
          retain: true
          payload: !lambda |-
            root["pin"] = "id7";
            root["enabled"] = id(id7).state;

Great thanks to your efforts!
Ngoc
Vietnam

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment