Skip to content

ESPHome

Eli Yu edited this page Nov 30, 2020 · 3 revisions

The codes can be downloaded:

Main YAML code file

Core Component

Setup device/board type and include self-defined UART read line sensor.

esphome:
  name: smart_cube_prototype
  platform: ESP32
  board: esp-wrover-kit
  includes:
    - uart_read_line_sensor.h

WIFI Component

Setup network and enable WIFI failure mode.

wifi:
  ssid: !secret_WIFI_SSID
  password: !secret_WIFI_PSW

  # Enable fallback hotspot (captive portal) in case wifi connection fails
  ap:
    ssid: "Smart Cube Prototype"
    password: "dsfiN6wHvXHV"

captive_portal:

Logger Component

Enable logging for debugging.

logger:
  level: VERBOSE #makes uart stream available in esphome logstream
  baud_rate: 0 #disable logging over uart

UART Component

Initialize UART interface, setup ports and baud rate.

uart:
  id: uart_mbed
  tx_pin: GPIO17
  rx_pin: GPIO16
  baud_rate: 9600

Time Component

The SNTP service is setup and two automations are setup for sending time/date update to Mbed through UART on every minute increment and day change.

time:
  - platform: sntp
    id: sntp_time
    # Push Time from NTP every minute
    on_time:
      - seconds: 0
        then:
          - uart.write:
              id: uart_mbed
              data: !lambda |-
                auto time_text = id(sntp_time).now().strftime("%H%M");
                return {0x2A, 0x74, 0x69, 0x3D, time_text.c_str()[0], time_text.c_str()[1], time_text.c_str()[2], time_text.c_str()[3], 0x0D};
      - seconds: 0
        minutes: 0
        hours: 0
        then:
          - uart.write:
              id: uart_mbed
              data: !lambda |-
                auto time_text = id(sntp_time).now().strftime("%Y%m%d%w");
                return {0x2A, 0x64, 0x61, 0x3D, time_text.c_str()[0], time_text.c_str()[1], time_text.c_str()[2], time_text.c_str()[3], time_text.c_str()[4], time_text.c_str()

Home Assistant API

The native integration API for home assistant is enabled for auto creation and detection of sensors and switches.

api:

OTA Component

The OTA (Over-The-Air) function is enabled for flashing memory with new code and debugging without wire.

ota:

Text Sensors

Declare the self-defined UART read line sensor, and setup a template text sensor to decode orientation detection result received from Mbed through UART.

text_sensor:
  # UART Readline Sensor
  - platform: custom
    lambda: |-
      auto my_custom_sensor = new UartReadLineSensor(id(uart_mbed));
      App.register_component(my_custom_sensor);
      return {my_custom_sensor};
    text_sensors:
      id: "uart_readline"
  # Orientation Sensor
  - platform: template
    lambda: |-
      if (id(uart_readline).state == "*ORI=L#") {
        return {"LEFT"};
      } else if(id(uart_readline).state == "*ORI=R#") {
        return {"RIGHT"};
      } else if(id(uart_readline).state == "*ORI=U#") {
        return {"UP"};
      } else {
        return {};
      }
    id: sensor_orientation
    name: Orientation Sensor
    update_interval: 1s

Switches

Four template switches are configured to mirror four smart home devices from home assistant, and changing states according to the commands received from Mbed through UART.

switch:
  # Controlled Devices
  - platform: template
    name: "Light 1"
    id: light_1
    lambda: |-
      if (id(uart_readline).state == "*L1=1#") {
        return true;
      } else if (id(uart_readline).state == "*L1=0#") {
        return false;
      } else {
        return {};
      }
  - platform: template
    name: "Light 2"
    id: light_2
    lambda: |-
      if (id(uart_readline).state == "*L2=1#") {
        return true;
      } else if (id(uart_readline).state == "*L2=0#") {
        return false;
      } else {
        return {};
      }
  - platform: template
    name: "Light 3"
    id: light_3
    lambda: |-
      if (id(uart_readline).state == "*L3=1#") {
        return true;
      } else if (id(uart_readline).state == "*L3=0#") {
        return false;
      } else {
        return {};
      }
  - platform: template
    name: "Light 4"
    id: light_4
    lambda: |-
      if (id(uart_readline).state == "*L4=1#") {
        return true;
      } else if (id(uart_readline).state == "*L4=0#") {
        return false;
      } else {
        return {};
      }

The built-in shutdown and restart switches are enabled for easy access and control from home assistant.

  # Built-in Power-Related Switches
  - platform: shutdown
    name: "Shutdown Switch"
    id: switch_shutdown
  - platform: restart
    name: "Restart Switch"
    id: switch_restart

A template switch is created for new notification reminder, being able to send command to Mbed to turn on the notification LED once a new notification appears in home assistant and clear the new notification flag once a vibration (notification dismiss) is detected and reported from Mbed.

  # Push New Notification Reminder
  - platform: template
    name: "New Notification"
    id: switch_new_not
    lambda: |-
      if (id(uart_readline).state == "*NOT DIS#") {
        return false;
      } else {
        return {};
      }
    turn_on_action:
      - uart.write: "*no=p\r"

A template switch to created to send smart home devices status to Mbed once being requested, and clear the state when a callback is received.

  # Push Controlled Devices States
  - platform: template
    name: "Pull Device"
    id: flag_pull_deivce_update
    lambda: |-
      if (id(uart_readline).state == "*DE=?#") {
        return true;
      } else if(id(uart_readline).state == "*DE GOT#") {
        return false;
      } else {
        return {};
      }
    on_turn_on:
      - uart.write:
          id: uart_mbed
          data: !lambda |-
            char l1;
            char l2;
            char l3;
            char l4;
            if (id(light_1).state) { l1 = '1'; }
            else { l1 = '0'; }
            if (id(light_2).state) { l2 = '1'; }
            else { l2 = '0'; }
            if (id(light_3).state) { l3 = '1'; }
            else { l3 = '0'; }
            if (id(light_4).state) { l4 = '1'; }
            else { l4 = '0'; }
            return {0x2A, 0x64, 0x65, 0x3D, l1, l2, l3, l4, 0x0D};

Binary Sensors

The built-in status sensor is enabled for easy monitoring of device connection status from Home Assistant.

binary_sensor:
  # Status Sensor
  - platform: status
    name: "Smart Cube Status"

A template binary sensor is created to relay the vibration detection information reported from the Mbed through UART, to Home Assistant.

  # Vibration Sensor
  - platform: template
    device_class: vibration
    id: sensor_vibration
    name: Vibration Sensor
    lambda: |-
      if (id(uart_readline).state == "*VI=Y#") {
        return true;
      } else if(id(uart_readline).state == "*VI=N#") {
        return false;
      } else {
        return {};
      }

Self-Defined UART Read Line Sensor

The custom component is referenced from the official ESPHome document.

#include "esphome.h"

class UartReadLineSensor : public Component, public UARTDevice, public TextSensor {
 public:
  UartReadLineSensor(UARTComponent *parent) : UARTDevice(parent) {}

  void setup() override {
    // nothing to do here
  }

  int readline(int readch, char *buffer, int len)
  {
    static int pos = 0;
    int rpos;

    if (readch > 0) {
      switch (readch) {
        case '\n': // Ignore new-lines
          break;
        case '\r': // Return on CR
          rpos = pos;
          pos = 0;  // Reset position index ready for next time
          return rpos;
        default:
          if (pos < len-1) {
            buffer[pos++] = readch;
            buffer[pos] = 0;
          }
      }
    }
    // No end of line has been found, so return -1.
    return -1;
  }

  void loop() override {
    const int max_line_length = 80;
    static char buffer[max_line_length];
    if (available() && readline(read(), buffer, max_line_length) > 0) {
      publish_state(buffer);
    }
  }
};