esphome / issues

Issue Tracker for ESPHome
https://esphome.io/
290 stars 34 forks source link

Rebooting bug report #132

Closed jptrsn closed 5 years ago

jptrsn commented 5 years ago

Operating environment/Installation (Hass.io/Docker/pip/etc.):

HassIO Add On ESP (ESP32/ESP8266, Board/Sonoff):

Wemos D1 Mini R2 Affected component:

WiFi connectivity

Description of problem: I know this is a known/understood bug, but I've stumbled across something odd which I wanted to report. I'm using github to host my configuration yaml file in a gist, so that I get version tracking and easy sharing. I've cloned this gist into the config/esphome/gist directory, and it comes in as config/esphome/gist/airconditioner1.yaml. I've also got a secrets.yaml file in there.

In the config/esphome directory, I've got another airconditioner1.yaml file (as this is what esphome will ingest).

If I copy/paste the contents from the gist file into the esphome file, the code runs as expected. However, I thought I was being pretty clever and using a single line in config/esphome/airconditioner1.yaml which was this:

<<: !include gist/airconditioner1.yaml

Using this method, the wemos suffers tcp disconnects. If I just replace the contents of the file with those of the gist, I get no disconnections.

Problem-relevant YAML-configuration entries:

substitutions:
  DEVICE_NAME: airconditioner1
  STATUS_PIN: D4
  COMPRESSOR_OUTPUT: D6
  COMPRESSOR_TIMEOUT: 15s #2min
  FAN_TIMEOUT: 15s # 2min
  FAN_ENABLE: D5
  FAN_SPEED: D7
  SDA: D1
  SCL: D2
  RESET: D0

esphome:
  name: airconditioner1
  platform: ESP8266
  board: d1_mini
  on_boot:
    then:
      - output.turn_off: compressor_output
      - output.turn_off: fan_output
      - output.turn_off: fan_speed_output
      - display.page.show: ac_idle

wifi:
  ssid: !secret ssid
  password: !secret wifi_password

# Enable logging
logger:

# Enable Home Assistant API
api:

ota:

mqtt:
  broker: !secret mqtt-ip
  username: !secret mqtt-user
  password: !secret mqtt-pass
  discovery: true
  id: mqtt_client

status_led:
  pin:
    number: $STATUS_PIN
    inverted: true

time:
  - platform: homeassistant
    id: time

binary_sensor:
  - platform: status
    name: "Status"

  - platform: template
    id: compressorSafeToTurnOff
    internal: true

  - platform: template
    id: fanSafeToTurnOff
    internal: true

output:
  - platform: gpio
    id: compressor_output
    pin: $COMPRESSOR_OUTPUT
    inverted: true

  - platform: gpio
    id: fan_output
    pin: $FAN_ENABLE
    inverted: true

  - platform: gpio
    id: fan_speed_output
    pin: $FAN_SPEED
    inverted: true

globals:
  - id: opMode # operation mode, 0 (off), 1 (auto), 2 (cool), 3 (fan_only)
    type: byte
    restore_value: no
    initial_value: '0'

  - id: targetTemp # target temperature
    type: byte
    restore_value: no
    initial_value: '21'

  - id: currentTemp
    type: byte
    restore_value: no

script:
  - id: compressor_on
    then:
      - script.execute: fan_on
      - output.turn_on: compressor_output
      - lambda: 'id(compressor_state).publish_state(true);'
      - lambda: 'id(compressorSafeToTurnOff).publish_state(false);'
      - delay: $COMPRESSOR_TIMEOUT
      - lambda: 'id(compressorSafeToTurnOff).publish_state(true);'

  - id: compressor_off
    then:
        - lambda: 'id(compressor_state).publish_state(false);'
        - wait_until:
            binary_sensor.is_on: compressorSafeToTurnOff
        - if:
            condition:
              lambda: 'return id(compressor_state).state == false;'
            then:
              - logger.log: "Turning off compressor"
              - output.turn_off: compressor_output
              - script.execute: fan_timeout
              - script.execute: fan_off

  - id: fan_timeout
    then:
      - lambda: 'id(fanSafeToTurnOff).publish_state(false);'
      - delay: $FAN_TIMEOUT
      - lambda: 'id(fanSafeToTurnOff).publish_state(true);'

  - id: fan_on
    then:
      - output.turn_on: fan_output
      - lambda: 'id(fan_state).publish_state(true);'

  - id: fan_off
    then:
      - logger.log: "Turn off fan"
      - lambda: 'id(fan_state).publish_state(false);'
      - wait_until:
          binary_sensor.is_on: fanSafeToTurnOff
      - if:
          condition:
            lambda: 'return id(fan_state).state == false;'
          then:
            - output.turn_off: fan_output

sensor:
  # Set temperature MQTT topic.
  - platform: mqtt_subscribe
    id: setTemp
    topic: climate/${DEVICE_NAME}/temp/set
    internal: true
    on_value:
      - then:
          - lambda: |-
              id(targetTemp) = (int)(id(setTemp).state);
          - mqtt.publish:
              topic: "climate/${DEVICE_NAME}/temp/state"
              payload: !lambda "return to_string(id(targetTemp));"

  # HTU21D used to determine ambient temperature. Can be replaced by any other temperature sensor (provided the logic remains the same)
  - platform: htu21d
    temperature:
      name: "Temperature"
      id: temp
      on_value:
        - then:
            - lambda: |-
                id(currentTemp) = id(temp).state;
            - mqtt.publish:
                topic: "climate/${DEVICE_NAME}/temp"
                payload: !lambda "return to_string(id(currentTemp));"
    humidity:
      name: "Humidity"
      id: hum
    update_interval: 60s

  # BH1750 Lux Sensor - not required for operation
  - platform: bh1750
    name: "Lux"
    id: lux
    address: 0x23
    update_interval: 60s

text_sensor:
  - platform: mqtt_subscribe
    id: setMode
    name: "Mode"
    topic: climate/${DEVICE_NAME}/mode/set
    # internal: true
    on_value:
      - then:
        - if:
            condition:
              lambda: |-
                if (id(setMode).state == "off") {
                  id(opMode) = 0;
                  return true;
                } else if (id(setMode).state == "auto") {
                  id(opMode) = 1;
                  return true;
                } else if (id(setMode).state == "cool") {
                  id(opMode) = 2;
                  return true;
                } else if (id(setMode).state == "fan_only") {
                  id(opMode) = 4;
                  return true;
                } else {
                  return false;
                }
            then:
              - mqtt.publish:
                  topic: "climate/${DEVICE_NAME}/mode"
                  payload: !lambda "return id(setMode).state;"

light:
  - platform: fastled_clockless
    chipset: WS2812B
    pin: D3
    num_leds: 8
    rgb_order: GRB
    name: "Air Conditioner Light"

switch:
  - platform: template
    name: "Compressor State"
    id: compressor_state
    icon: "mdi:snowflake"
    turn_on_action:
      - script.execute: compressor_on
    turn_off_action:
      - script.execute: compressor_off

  - platform: template
    name: "Fan State"
    id: fan_state
    icon: "mdi:fan"
    turn_on_action:
      - script.execute: fan_on
    turn_off_action:
      - script.execute: fan_off

  - platform: template
    name: "Fan Speed"
    id: fan_speed

font:
- file: 'slkscr.ttf'
  id: font1
  size: 8

- file: 'bebas.ttf'
  id: font2
  size: 36
  glyphs: "0123456789: "

- file: 'arial_narrow_7.ttf'
  id: font3
  size: 12
  glyphs: "0123456789°%."

image:
  - file: "fan-large.png"
    id: fanHighIcon
  - file: "fan_outline-large.png"
    id: fanLowIcon
  - file: "snowflake-large.png"
    id: coolIcon

i2c:
  sda: $SDA
  scl: $SCL
  scan: False

display:
  - platform: ssd1306_i2c
    model: "SH1106 128x64"
    reset_pin: $RESET
    address: 0x3C
    id: oled
    pages:
      - id: ac_idle
        lambda: |-

          it.printf(64, 0, id(font1), TextAlign::TOP_CENTER, "Air Conditioner");

          // Print time in HH:MM format
          it.strftime(42, 0, id(font2), TextAlign::TOP_CENTER, "%H:%M", id(time).now());

          // Print temperature
          if (id(temp).has_state()) {
            it.printf(3, 50, id(font3), TextAlign::TOP_LEFT , "%.1f°", id(temp).state);
          }

          // Print humidity
          if (id(hum).has_state()) {
            it.printf(42, 50, id(font3), TextAlign::TOP_CENTER , "%.0f%%", id(hum).state);
          }

          // Print lux
          if (id(lux).has_state()) {
            it.printf(80, 50, id(font3), TextAlign::TOP_RIGHT , "%.0f", id(lux).state);
          }

          if (id(compressor_state).state) {
            it.image(80, 12, id(coolIcon));
          } else if (id(fan_state).state) {
            if (id(fan_speed).state) {
              it.image(80, 12, id(fanHighIcon));
            } else {
              it.image(80, 12, id(fanLowIcon));
            }
          }

Traceback (if applicable):

Additional information and things you've tried:

OttoWinter commented 5 years ago

That is not possible. When ESPHome reads the config it directly replaces all content with the <<:. The result is that it cannot modify anything - and I'm 100% certain about that. If you want to check, you can use the validate script to see how esphome interprets the config.

What is likely the issue here is that you have mqtt and api enabled. But that will make the ESP reboot every 5min because no client connected over the api.

Please see the warning in the mqtt docs

jptrsn commented 5 years ago

I'm using the time component with the API. Is there an MQTT equivalent?

jptrsn commented 5 years ago

Decided to attempt to use only the native api.