Giter VIP home page Giter VIP logo

nspanel_thermostat's Issues

1

Note: this may not be needed if the pull request has been merged.

Check esphome/esphome#2956 for current status.

external_components:

  • source: github://pr#2956
    components: [nextion]
    refresh: 1h

Set some variables for convenience

substitutions:
node_name: nspanel
device_name: NSPanel
target_temp_normal: 21.0 °C
target_temp_away: 21.0 °C

esphome:
name: $node_name
comment: $device_name

esp32:
board: esp32dev

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

# Optional manual IP

manual_ip:
static_ip: 192.168.1.74
gateway: 192.168.1.1
subnet: 255.255.255.0

Enable fallback hotspot (captive portal) in case wifi connection fails

ap:
ssid: "Panel Fallback Hotspot"
password: "MsRx7nEeio2B"

Enable logging

logger:
baud_rate: 0
level: VERBOSE
logs:
rtttl: none
#homeassistant: DEBUG
binary_sensor: none
nextion: none
ledc.output: none
resistance: none
ntc: none
sensor: none
sensor.filter: none
nextion_sensor: none
api.service: none
esp32.preferentes: none
#climate: DEBUG
#homeassistant.service: DEBUG
scheduler: none
json: none
api: none

Enable wireless updates

ota:
password: !secret ota_pwd

Enable Home Assistant API

api:
encryption:
key: "Y/HgkY8GkhF5U3W2sFwXd0302o72Jz/aaHS+flR0dIY="
services:
# Service to play a song
- service: play_rtttl
variables:
song_str: string
then:
- rtttl.play:
rtttl: !lambda 'return song_str;'
- service: upload_tft
then:
- lambda: 'id(disp1)->upload_tft();'

- service: send_command

variables:

cmd: string

then:

- lambda: 'id(disp1).send_command_printf("%s", cmd.c_str());'

web_server:
port: 80

time:

  • platform: homeassistant
    id: homeassistant_time
    timezone: Europe/Madrid
    on_time:
    • seconds: 0
      minutes: '*'
      then:
      • lambda: |-
        id(disp1).set_component_text_printf("page0.wind", "%i km/h", (int)id(wind_speed).state);

- script.execute: tft_date_update

- script.execute: tft_time_update

- script.execute: tft_weather_update

A reboot button is always useful

button:

  • platform: restart
    name: Restart $device_name

Define some inputs

binary_sensor:

Switches between HEAT or OFF mode

  • platform: gpio
    name: $device_name Left Button
    pin:
    number: 14
    inverted: true
    on_press:
    then:
    - climate.control:
    id: caldera
    mode: !lambda |-
    if (id(caldera).mode==CLIMATE_MODE_OFF)
    {
    return CLIMATE_MODE_HEAT;
    }
    else
    {
    return CLIMATE_MODE_OFF;
    }
    - lambda: !lambda |-
    if (id(caldera).mode==CLIMATE_MODE_OFF)
    {
    id(disp1).set_component_text_printf("page0.btn0", "APAGAR");
    }
    else
    {
    id(disp1).set_component_text_printf("page0.btn0", "ENCENDER");
    }

- logger.log: id(caldera).mode

    - script.execute: tft_wake_up

Switches between a predefined "night" or "away" target temperature and a "normal" target temperature

this will be also automated in homeassistant, but it is nice to have a button for it

  • platform: gpio
    name: $device_name Right Button
    pin:
    number: 27
    inverted: true
    on_press:
    then:
    - climate.control:
    id: caldera
    mode: !lambda |-
    if (id(caldera).mode==CLIMATE_MODE_HEAT)
    {
    id(disp1).set_component_text_printf("page0.btn1", "ACTIVO : FRIO");
    return CLIMATE_MODE_COOL;

          }
          else
          {
            id(disp1).set_component_text_printf("page0.btn1", "ACTIVO : CALOR");
            return CLIMATE_MODE_HEAT;
          }
    - lambda: !lambda |-
        if (id(caldera).mode==CLIMATE_MODE_HEAT)
        {
        id(disp1).set_component_text_printf("page0.btn1", "ACTIVO : FRIO");
        }
        else
        {
        id(disp1).set_component_text_printf("page0.btn1", "ACTIVO : CALOR");
        }
    

- logger.log: id(caldera).mode

    - script.execute: tft_wake_up
  • platform: nextion
    name: $device_name Up Button
    page_id: 0
    component_id: 6
    on_press:
    then:
    - climate.control:
    id: caldera
    target_temperature_low: !lambda |-
    if ( id(caldera).mode == CLIMATE_MODE_COOL )
    {
    return id(caldera).target_temperature_low + 0.5;
    }
    else
    {
    return id(caldera).target_temperature_low;
    }
    target_temperature_high: !lambda |-
    if ( id(caldera).mode == CLIMATE_MODE_HEAT )
    {
    return id(caldera).target_temperature_high + 0.5;
    }
    else
    {
    return id(caldera).target_temperature_high;
    }
    - lambda: !lambda |-
    if ( id(caldera).mode == CLIMATE_MODE_COOL )
    {
    id(disp1).set_component_text_printf("page0.setTemp", "%.1f""\xb0", id(caldera).target_temperature_low);
    }
    else
    {
    id(disp1).set_component_text_printf("page0.setTemp", "%.1f""\xb0", id(caldera).target_temperature_high);
    }

preset: HOME

- script.execute: update_target_temperature

- rtttl.play: "twobits:d=4,o=5,b=220:c6,8g"

  • platform: nextion
    name: $device_name Down Button
    page_id: 0
    component_id: 7
    on_press:
    then:

    - climate.control:
        id: caldera
        target_temperature_low: !lambda |-
          if ( id(caldera).mode == CLIMATE_MODE_COOL )
          {
          return id(caldera).target_temperature_low - 0.5;
          id(disp1).set_component_text_printf("page0.setTemp", "%.1f""\xb0", id(caldera).target_temperature_low);
          }
          else
          {
          return id(caldera).target_temperature_low;
          id(disp1).set_component_text_printf("page0.setTemp", "%.1f""\xb0", id(caldera).target_temperature_low);
          }
        target_temperature_high: !lambda |-
          if ( id(caldera).mode == CLIMATE_MODE_HEAT )
          {
          return id(caldera).target_temperature_high - 0.5;
          id(disp1).set_component_text_printf("page0.setTemp", "%.1f""\xb0", id(caldera).target_temperature_high);
          }
          else
          {
          return id(caldera).target_temperature_high;
          id(disp1).set_component_text_printf("page0.setTemp", "%.1f""\xb0", id(caldera).target_temperature_high);
          }
    - lambda: !lambda |-
          if ( id(caldera).mode == CLIMATE_MODE_COOL )
          {
          id(disp1).set_component_text_printf("page0.setTemp", "%.1f""\xb0", id(caldera).target_temperature_low);
          }
          else
          {
          id(disp1).set_component_text_printf("page0.setTemp", "%.1f""\xb0", id(caldera).target_temperature_high);
          }
    

- script.execute: update_target_temperature

- rtttl.play: "twobits:d=4,o=5,b=220:c6,8g"

- script.execute: update_target_temperature

- rtttl.play: "twobits:d=4,o=5,b=220:c6,8g"

sensor:

  • platform: wifi_signal
    name: $device_name WiFi Signal
    update_interval: 60s

  • platform: adc
    id: ntc_source
    pin: 38
    update_interval: 10s
    attenuation: 11db

  • platform: resistance
    id: resistance_sensor
    sensor: ntc_source
    configuration: DOWNSTREAM
    resistor: 11.2kOhm

  • platform: ntc
    id: temperature
    sensor: resistance_sensor
    accuracy_decimals: 2
    filters:

    • median:
      window_size: 15
      send_every: 10
      send_first_at: 3
      calibration:
      b_constant: 3950
      reference_temperature: 25°C
      reference_resistance: 10kOhm
      name: $device_name Temperature
      on_value:
      then:
      • lambda: 'id(disp1).set_component_text_printf("page0.intTemp", "%.1f""\xb0", x);'

Grab current temperature from Home Assistant

  • platform: homeassistant
    id: ext_temperature
    entity_id: sensor.exterior_temperature
    attribute: temperature
    on_value:
    then:
    - lambda: 'id(disp1).set_component_text_printf("page0.extTemp", "%.1f""\xb0", x);'

  • platform: homeassistant
    id: wind_speed
    entity_id: weather.aemet_daily
    attribute: wind_speed
    unit_of_measurement: "km/h"
    on_value:
    then:
    - lambda: 'id(disp1).set_component_text_printf("page0.wind", "%i km/h""\xb0", (int)id(wind_speed).state);'

  • platform: nextion
    id: current_page
    name: "current_page"
    internal: true
    accuracy_decimals: 0
    variable_name: dp
    update_interval: 1s

text_sensor:

  • platform: homeassistant
    id: current_weather
    entity_id: weather.aemet_daily
    on_value:
    then:
    - script.execute: tft_weather_update

script:

  • id: tft_weather_update
    then:

    • lambda: |-
      char const *wstr[] = {"clear-night", "cloudy", "fog",
      "lightning", "lightning-rainy", "partlycloudy",
      "pouring", "rainy", "snowy", "sunny"};
      int i = 0;
      while ((id(current_weather).state!=wstr[i])&&(i<12)) {i++;}
      id(disp1).send_command_printf("page0.weather.pic=%i", i+3);
      id(disp1).set_component_text_printf("page0.wind", "%i km/h", (int)id(wind_speed).state);
  • id: tft_date_update
    then:

    • lambda: |-
      int dia = id(homeassistant_time).now().day_of_month;
      int mes = id(homeassistant_time).now().month;
      char const *dia_semana[] = {"Domingo", "Lunes", "Martes", "Mierco.", "Jueves", "Viernes", "Sabado"};
      const char *str = dia_semana[id(homeassistant_time).now().day_of_week-1]; // range [1-7], Domingo=1
      id(disp1).set_component_text_printf("page0.date", "%s %02i/%02i", str, dia, mes);
  • id: tft_time_update
    then:

    • lambda: 'id(disp1).set_component_text_printf("page0.time", "%s", id(homeassistant_time).now().strftime("%H:%M").c_str());'
  • id: tft_wake_up
    then:

    • lambda: |-
      id(disp1).send_command_printf("page0.sleep_cnt.val=page0.sleep_timeout.val");
      id(disp1).send_command_printf("page0.sleep_timer.es=1");
      if (id(current_page).state!=0)
      id(disp1).send_command_printf("page 0");
      id(disp1).send_command_printf("dim=page0.brightness.val");
  • id: abrir_frio
    then:

    • logger.log: COOL - abrimos rejilla
    • homeassistant.service:
      service: cover.open_cover
      data:
      entity_id: cover.dormitorio
  • id: abrir_calor
    then:

    • logger.log: HEAT - abrimos rejilla
    • homeassistant.service:
      service: cover.open_cover
      data:
      entity_id: cover.dormitorio
  • id: cerrar
    then:

    • homeassistant.service:
      service: cover.stop_cover
      data:
      entity_id: cover.dormitorio

Define some outputs

switch:

Relay 2 is the thermostat switch, Relay 1 was physically removed!

  • platform: gpio
    name: $device_name Relay
    id: relay_2
    internal: true # it should not be activated directly by home assitant
    pin:
    number: 19

Pin 4 always needs to be on to power up the display

  • platform: gpio
    id: screen_power
    entity_category: config
    pin:
    number: 4
    inverted: true
    restore_mode: ALWAYS_ON

  • platform: template
    name: $device_name auto sleep
    id: auto_sleep
    entity_category: config
    restore_state: true
    optimistic: true
    on_turn_on:

    • lambda: 'id(disp1).send_command_printf("page0.disable_sleep.val=0");'
      on_turn_off:
    • lambda: 'id(disp1).send_command_printf("page0.disable_sleep.val=1");'

number:

  • platform: template
    name: $device_name Brightness
    id: brightness
    entity_category: config
    unit_of_measurement: '%'
    icon: "mdi:brightness-percent"
    min_value: 0
    max_value: 100
    step: 1
    initial_value: 20
    set_action:
    then:
    - lambda: |-
    id(disp1).send_command_printf("page0.sleep_timer.en=1");
    if (id(current_page).state!=0)
    id(disp1).send_command_printf("page 0");
    id(disp1).set_backlight_brightness(x/100);

Sets the sleep timer value

requires code running in the nextion tft to make a 1 second period timer

with a counter and a variable to store the timeout

  • platform: template
    name: $device_name Sleep timeout
    id: sleep_timeout
    entity_category: config
    unit_of_measurement: 's'
    icon: "mdi:timer"
    min_value: 3
    max_value: 300
    step: 1
    initial_value: 30
    set_action:
    then:
    - lambda: |-
    id(disp1).send_command_printf("page0.sleep_timeout.val=%i", (int)x); // set the timeout
    id(disp1).send_command_printf("page0.sleep_cnt.val=%i", (int)x); // reset the counter to its maximum

Configure the internal bleeper

output:

  • platform: ledc
    id: buzzer_out
    pin:
    number: 21

Enable ringtone music support

rtttl:
id: buzzer
output: buzzer_out

Configure UART for communicating with the screen

uart:
id: tf_uart
tx_pin: 16
rx_pin: 17
baud_rate: 115200

Configure the screen

display:

  • platform: nextion
    id: disp1
    uart_id: tf_uart
    tft_url: http://192.168.1.252:8123/local/nspanel_thermostat/nspanel_thermostat.tft
    on_setup:
    then:
    - number.set:
    id: brightness
    value: 20
    - lambda: |-
    id(disp1).set_component_text_printf(
    "page0.intTemp", "%.1f""\xb0", id(temperature).state);
    id(disp1).set_component_text_printf(
    "page0.extTemp", "%.1f""\xb0", id(ext_temperature).state);
    id(disp1).set_component_text_printf("page0.btn0", "APAGAR");
    id(disp1).set_component_text_printf("page0.btn1", "ACTIVO : CALOR");

- script.execute: tft_date_update

- script.execute: tft_time_update

- script.execute: tft_weather_update

- rtttl.play: "twobits:d=4,o=5,b=220:c6,8g,8g,a,g,p,b,c6"

Single-point thermostat (for heating only)

climate:

  • platform: thermostat
    id: caldera
    name: $device_name Thermostat
    sensor: temperature
    default_target_temperature_low: 18
    default_target_temperature_high: 28

    heat_deadband: 0.2
    heat_overrun: 0.2
    cool_deadband: 0.2
    cool_overrun: 0.2

    min_heating_off_time: 1s
    min_heating_run_time: 1s
    min_cooling_off_time: 1s
    min_cooling_run_time: 1s

    min_idle_time: 1s

    cool_action:

    • script.execute: abrir_frio

- switch.turn_on: relay_2

heat_action:
  - script.execute: abrir_calor

- switch.turn_on: relay_2

idle_action:
  - logger.log: IDLE - cerramos rejilla
  - script.execute: cerrar

- switch.turn_off: relay_2

on_state:
  - logger.log: "estoy encendido"
  - lambda: !lambda |-
          if ( id(caldera).mode == CLIMATE_MODE_COOL )
          {
          id(disp1).set_component_text_printf("page0.setTemp", "%.1f""\xb0", id(caldera).target_temperature_low);
          }
           else
          {
          id(disp1).set_component_text_printf("page0.setTemp", "%.1f""\xb0", id(caldera).target_temperature_high);
          }

visual:
  min_temperature: 18
  max_temperature: 28
  temperature_step: 0.1
away_config:
  default_target_temperature_low: 19
  default_target_temperature_high: 27

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.