Add support for addon_climate_cool
This commit is contained in:
@@ -1,17 +1,20 @@
|
||||
# Add-on: Climate
|
||||
|
||||
## Description
|
||||
This add-on enables the use of your panel's relays to act as a thermostat (heater only for now) using the internal temperature sensor and independent of the network availability.
|
||||
This add-on enables the use of your panel's relays to act as a thermostat (either cooler or heater) using the internal temperature sensor and independent of the network availability.
|
||||
|
||||
### Attention
|
||||
The NSPanel is limited to 2A per relay. Don't use it for directly power your heater if exceeding the panel specifications:
|
||||
- 150W/110V/Gang, 300W/110V/Total
|
||||
- 300W/220V/Gang, 600W/220V/Total
|
||||
More details on the [Sonoff NSPanel's page](https://sonoff.tech/product/central-control-panel/nspanel/) and the [product specifications document](https://sonoff.tech/wp-content/uploads/2021/11/%E4%BA%A7%E5%93%81%E5%8F%82%E6%95%B0%E8%A1%A8-NSPanel-20210831.pdf).
|
||||
1. The NSPanel is limited to 2A per relay. Don't use it for directly power your cooler/heater if exceeding the panel specifications:
|
||||
- 150W/110V/Gang, 300W/110V/Total
|
||||
- 300W/220V/Gang, 600W/220V/Total<br>
|
||||
- More details on the [Sonoff NSPanel's page](https://sonoff.tech/product/central-control-panel/nspanel/) and the [product specifications document](https://sonoff.tech/wp-content/uploads/2021/11/%E4%BA%A7%E5%93%81%E5%8F%82%E6%95%B0%E8%A1%A8-NSPanel-20210831.pdf).
|
||||
|
||||
2. At this moment you have to choose between `heat` or `cool`. The dual/simultaneous operation is not supported at this moment.
|
||||
3. A target temperature must be set on the climate entity in Home Assistant or the page Climate in your panel.
|
||||
|
||||
|
||||
## Installation
|
||||
You will need to add the reference to the `addon_climate` file on your ESPHome settings in the `package` section and after te `remote_package` (base code), as shown bellow:
|
||||
You will need to add the reference to `addon_climate_heat` or `addon_climate_cool` files on your ESPHome settings in the `package` section and after te `remote_package` (base code), as shown bellow (for `heat` in this example):
|
||||
|
||||
```yaml
|
||||
substitutions:
|
||||
@@ -35,7 +38,9 @@ packages:
|
||||
ref: main
|
||||
files:
|
||||
- nspanel_esphome.yaml # Core package
|
||||
# - nspanel_esphome_addon_climate_cool.yaml # activate for local climate (cooling) control
|
||||
- nspanel_esphome_addon_climate_heat.yaml # activate for local climate (heater) control
|
||||
|
||||
refresh: 300s
|
||||
```
|
||||
|
||||
@@ -43,22 +48,60 @@ packages:
|
||||
|
||||
The following keys are available to be used in your `substitutions`:
|
||||
|
||||
|Key|Required|Supported values|Default|Description|
|
||||
|:-|:-:|:-:|:-:|:-|
|
||||
|heater_relay|Mandatory|`1` or `2`|`0` (disabled)|Relay used for control the heater. User `1` for "Relay 1" or `2` for "Relay 2".|
|
||||
|temp_units|Optional|`°C` or `°F`|`°C`|Temperature unit.|
|
||||
|min_off_time|Optional|Positive integer representing the number of seconds|`300`|Minimum duration (in seconds) the heating action must be disengaged before it may be engaged.|
|
||||
|min_run_time|Optional|Positive integer representing the number of seconds|`300`|Minimum duration (in seconds) the heating action must be engaged before it may be disengaged.|
|
||||
|min_idle_time|Optional|Positive integer representing the number of seconds|`30`|Minimum duration (in seconds) the idle action must be active before calling another climate action.|
|
||||
|temp_min|Optional|Number representing a temperature in the selected unit|`5`|The minimum temperature the climate device can reach. Used to set the range of the frontend gauge.|
|
||||
|temp_max|Optional|Number representing a temperature in the selected unit|`25`|The maximum temperature the climate device can reach. Used to set the range of the frontend gauge.|
|
||||
|temp_step|Optional|Number representing a temperature in the selected unit|`0.5`|The granularity with which the target temperature can be controlled.|
|
||||
Key|Required|Supported values|Default|Description
|
||||
:-|:-:|:-:|:-:|:-
|
||||
cooler_relay|Mandatory for `cool`|`1` or `2`|`0` (disabled)|Relay used for control the cooler. User `1` for "Relay 1" or `2` for "Relay 2".
|
||||
heater_relay|Mandatory for `heat`|`1` or `2`|`0` (disabled)|Relay used for control the heater. User `1` for "Relay 1" or `2` for "Relay 2".
|
||||
temp_units|Optional|`°C` or `°F`|`°C`|Temperature unit.
|
||||
min_off_time|Optional|Positive integer representing the number of seconds|`300`|Minimum duration (in seconds) the cooling/heating action must be disengaged before it may be engaged.
|
||||
min_run_time|Optional|Positive integer representing the number of seconds|`300`|Minimum duration (in seconds) the cooling/heating action must be engaged before it may be disengaged.
|
||||
min_idle_time|Optional|Positive integer representing the number of seconds|`30`|Minimum duration (in seconds) the idle action must be active before calling another climate action.
|
||||
temp_min|Optional|Number representing a temperature in the selected unit|`5`|The minimum temperature the climate device can reach. Used to set the range of the frontend gauge.
|
||||
temp_max|Optional|Number representing a temperature in the selected unit|`25`|The maximum temperature the climate device can reach. Used to set the range of the frontend gauge.
|
||||
temp_step|Optional|Number representing a temperature in the selected unit|`0.5`|The granularity with which the target temperature can be controlled.
|
||||
|
||||
- All values must be delimited with `""`
|
||||
- For more details on the keys, please take a look at [ESPHome Base Climate Configurations](https://esphome.io/components/climate/index.html#base-climate-configuration) and [ESPHome Climate Thermostat - Additional actions behavior](https://esphome.io/components/climate/thermostat.html#additional-actions-behavior).
|
||||
|
||||
### Example:
|
||||
|
||||
### Examples:
|
||||
|
||||
#### Cooler:
|
||||
|
||||
```yaml
|
||||
substitutions:
|
||||
###### CHANGE ME START ######
|
||||
device_name: "YOUR_NSPANEL_NAME"
|
||||
wifi_ssid: !secret wifi_ssid
|
||||
wifi_password: !secret wifi_password
|
||||
|
||||
nextion_update_url: "http://homeassistant.local:8123/local/nspanel_us.tft"
|
||||
|
||||
|
||||
##### addon-configuration #####
|
||||
## addon_climate ##
|
||||
cooler_relay: "1" #Use relay 1
|
||||
temp_units: "°F" #Temperatures in Fahrenheit
|
||||
temp_min: "40" #Min supported temperature is 40°F
|
||||
temp_max: "80" #Max supported temperature is 80°F
|
||||
temp_step: "1" #Temperature granularity is 1°F
|
||||
|
||||
##### CHANGE ME END #####
|
||||
|
||||
|
||||
packages:
|
||||
remote_package:
|
||||
url: https://github.com/Blackymas/NSPanel_HA_Blueprint
|
||||
ref: main
|
||||
files:
|
||||
- nspanel_esphome.yaml # Core package
|
||||
- nspanel_esphome_addon_climate_cool.yaml # activate for local climate (cooling) control
|
||||
# - nspanel_esphome_addon_climate_heat.yaml # activate for local climate (heater) control
|
||||
refresh: 300s
|
||||
```
|
||||
|
||||
|
||||
#### Heater:
|
||||
|
||||
```yaml
|
||||
substitutions:
|
||||
@@ -87,6 +130,7 @@ packages:
|
||||
ref: main
|
||||
files:
|
||||
- nspanel_esphome.yaml # Core package
|
||||
# - nspanel_esphome_addon_climate_cool.yaml # activate for local climate (cooling) control
|
||||
- nspanel_esphome_addon_climate_heat.yaml # activate for local climate (heater) control
|
||||
refresh: 300s
|
||||
```
|
||||
|
||||
290
nspanel_esphome_addon_climate_cool.yaml
Normal file
290
nspanel_esphome_addon_climate_cool.yaml
Normal file
@@ -0,0 +1,290 @@
|
||||
####################################################################################################
|
||||
##### NSPanel ESPHome Add-on for Climate control - Heat #####
|
||||
##### Add-on for https://github.com/Blackymas/NSPanel_HA_Blueprint #####
|
||||
####################################################################################################
|
||||
|
||||
substitutions:
|
||||
### Local thermostat defaults ###
|
||||
# https://esphome.io/components/climate/thermostat.html
|
||||
temp_units: "°C"
|
||||
heater_relay: "0" # Select 1 for "Relay 1", 2 for "Relay 2" or "0" to a dummy switch/disabled
|
||||
min_off_time: "300"
|
||||
min_run_time: "300"
|
||||
min_idle_time: "30"
|
||||
# https://esphome.io/components/climate/index.html#base-climate-configuration
|
||||
temp_min: "5"
|
||||
temp_max: "25"
|
||||
temp_step: "0.5"
|
||||
|
||||
climate:
|
||||
- platform: thermostat
|
||||
name: ${device_name} Thermostat
|
||||
id: thermostat_embedded
|
||||
sensor: temp_nspanel
|
||||
min_heating_off_time: ${min_off_time}s
|
||||
min_heating_run_time: ${min_run_time}s
|
||||
min_idle_time: ${min_idle_time}s
|
||||
visual:
|
||||
min_temperature: ${temp_min} ${temp_units}
|
||||
max_temperature: ${temp_max} ${temp_units}
|
||||
temperature_step: ${temp_step} ${temp_units}
|
||||
heat_action:
|
||||
- switch.turn_on: relay_${heater_relay}
|
||||
idle_action:
|
||||
- switch.turn_off: relay_${heater_relay}
|
||||
default_preset: "Off"
|
||||
on_boot_restore_from: memory
|
||||
preset:
|
||||
- name: "Off"
|
||||
default_target_temperature_low: ${temp_min} ${temp_units}
|
||||
mode: "off"
|
||||
- name: Home
|
||||
default_target_temperature_low: 21 ${temp_units}
|
||||
internal: false
|
||||
on_state:
|
||||
- logger.log: Climate state changed - Start
|
||||
- script.execute:
|
||||
id: addon_climate_update_page_climate
|
||||
- logger.log: Climate state changed - End
|
||||
|
||||
globals:
|
||||
##### Is embedded thermostat set as main climate entity? #####
|
||||
- id: is_embedded_thermostat
|
||||
type: bool
|
||||
restore_value: true
|
||||
initial_value: 'false'
|
||||
##### Is embedded thermostat visible on climate page? #####
|
||||
- id: is_addon_climate_visible
|
||||
type: bool
|
||||
restore_value: false
|
||||
initial_value: 'false'
|
||||
|
||||
script:
|
||||
- id: !extend addon_climate_update_page_home
|
||||
mode: restart
|
||||
then:
|
||||
- if:
|
||||
condition:
|
||||
- binary_sensor.is_on: nextion_init
|
||||
then:
|
||||
- lambda: |-
|
||||
// Update home.entity variable
|
||||
id(disp1).set_component_text_printf("home.entity", (id(is_embedded_thermostat)) ? "embedded_climate" : "");
|
||||
//if (id(is_embedded_thermostat)) id(disp1).set_component_text_printf("home.entity", "embedded_climate");
|
||||
//else id(disp1).set_component_text_printf("home.entity", "");
|
||||
|
||||
- if:
|
||||
condition:
|
||||
- lambda: !lambda 'return id(is_embedded_thermostat);'
|
||||
then:
|
||||
- lambda: |-
|
||||
// Update chips
|
||||
ESP_LOGV("script.refresh_chips_climate", "thermostat_embedded.action=%i", int(id(thermostat_embedded).action));
|
||||
switch (int(id(thermostat_embedded).action)) // CLIMATE_ACTION_OFF = 0, CLIMATE_ACTION_COOLING = 2, CLIMATE_ACTION_HEATING = 3, CLIMATE_ACTION_IDLE = 4, CLIMATE_ACTION_DRYING = 5, CLIMATE_ACTION_FAN = 6
|
||||
{
|
||||
case 0: //CLIMATE_ACTION_OFF
|
||||
ESP_LOGV("script.refresh_chips_climate", "thermostat_embedded.mode=%i", int(id(thermostat_embedded).mode));
|
||||
switch (int(id(thermostat_embedded).mode)) // CLIMATE_MODE_OFF = 0, CLIMATE_MODE_HEAT_COOL = 1, CLIMATE_MODE_COOL = 2, CLIMATE_MODE_HEAT = 3, CLIMATE_MODE_FAN_ONLY = 4, CLIMATE_MODE_DRY = 5, CLIMATE_MODE_AUTO = 6
|
||||
{
|
||||
case 0: //CLIMATE_MODE_OFF
|
||||
id(disp1).set_component_text_printf("home.icon_top_03", "%s", "\uFFFF"); // (E424) Don't show icon when off
|
||||
id(disp1).set_component_font_color("home.icon_top_03", 35921);
|
||||
break;
|
||||
case 1: //CLIMATE_MODE_HEAT_COOL
|
||||
id(disp1).set_component_text_printf("home.icon_top_03", "%s", "\uE069");
|
||||
id(disp1).set_component_font_color("home.icon_top_03", 35921);
|
||||
break;
|
||||
case 2: //CLIMATE_MODE_COOL
|
||||
id(disp1).set_component_text_printf("home.icon_top_03", "%s", "\uE716");
|
||||
id(disp1).set_component_font_color("home.icon_top_03", 35921);
|
||||
break;
|
||||
case 3: //CLIMATE_MODE_HEAT
|
||||
id(disp1).set_component_text_printf("home.icon_top_03", "%s", "\uE237");
|
||||
id(disp1).set_component_font_color("home.icon_top_03", 64164);
|
||||
break;
|
||||
case 4: //CLIMATE_MODE_FAN_ONLY
|
||||
id(disp1).set_component_text_printf("home.icon_top_03", "%s", "\uE20F");
|
||||
id(disp1).set_component_font_color("home.icon_top_03", 35921);
|
||||
break;
|
||||
case 5: //CLIMATE_MODE_DRY
|
||||
id(disp1).set_component_text_printf("home.icon_top_03", "%s", "\uE58D");
|
||||
id(disp1).set_component_font_color("home.icon_top_03", 35921);
|
||||
break;
|
||||
case 6: //CLIMATE_MODE_AUTO
|
||||
id(disp1).set_component_text_printf("home.icon_top_03", "%s", "\uEE8D");
|
||||
id(disp1).set_component_font_color("home.icon_top_03", 35921);
|
||||
break;
|
||||
}
|
||||
case 2: //CLIMATE_ACTION_COOLING
|
||||
id(disp1).set_component_text_printf("home.icon_top_03", "%s", "\uE716");
|
||||
id(disp1).set_component_font_color("home.icon_top_03", 1055);
|
||||
break;
|
||||
case 3: //CLIMATE_ACTION_HEATING
|
||||
id(disp1).set_component_text_printf("home.icon_top_03", "%s", "\uE237");
|
||||
id(disp1).set_component_font_color("home.icon_top_03", 64164);
|
||||
break;
|
||||
case 4: //CLIMATE_ACTION_IDLE
|
||||
id(disp1).set_component_text_printf("home.icon_top_03", "%s", "\uE50E"); // mdi:thermometer
|
||||
id(disp1).set_component_font_color("home.icon_top_03", 35921);
|
||||
break;
|
||||
case 5: //CLIMATE_ACTION_DRYING
|
||||
id(disp1).set_component_text_printf("home.icon_top_03", "%s", "\uE58D");
|
||||
id(disp1).set_component_font_color("home.icon_top_03", 64704);
|
||||
break;
|
||||
case 6: //CLIMATE_ACTION_FAN
|
||||
id(disp1).set_component_text_printf("home.icon_top_03", "%s", "\uE20F");
|
||||
id(disp1).set_component_font_color("home.icon_top_03", 1530);
|
||||
break;
|
||||
}
|
||||
|
||||
- id: !extend addon_climate_service_call
|
||||
then:
|
||||
- lambda: |-
|
||||
ESP_LOGV("script.addon_climate_service_call", "Starting");
|
||||
id(is_addon_climate_visible) = true;
|
||||
auto call = id(thermostat_embedded).make_call();
|
||||
if (key == "set_temperature")
|
||||
{
|
||||
call.set_target_temperature(stof(value) / 10);
|
||||
}
|
||||
else if (key == "hvac_mode")
|
||||
{
|
||||
call.set_mode(value);
|
||||
}
|
||||
call.perform();
|
||||
ESP_LOGV("script.addon_climate_service_call", "Finished");
|
||||
|
||||
- id: !extend addon_climate_set_climate
|
||||
then:
|
||||
- lambda: |-
|
||||
ESP_LOGV("script.addon_climate_set_climate", "Starting");
|
||||
id(is_addon_climate_visible) = embedded_climate;
|
||||
ESP_LOGV("script.addon_climate_set_climate", "Finished");
|
||||
|
||||
- id: !extend addon_climate_global_settings
|
||||
then:
|
||||
- lambda: |-
|
||||
ESP_LOGV("script.addon_climate_global_settings", "Starting");
|
||||
id(is_embedded_thermostat) = embedded_climate;
|
||||
ESP_LOGV("script.addon_climate_global_settings", "Finished");
|
||||
|
||||
- id: !extend addon_climate_update_page_climate
|
||||
then:
|
||||
- lambda: ESP_LOGV("script.addon_climate_update_page_climate", "Starting");
|
||||
- if:
|
||||
condition:
|
||||
- binary_sensor.is_on: nextion_init
|
||||
- text_sensor.state: # Is climate page visible?
|
||||
id: current_page
|
||||
state: 'climate'
|
||||
- lambda: !lambda return id(is_addon_climate_visible);
|
||||
then: # Embedded thermostat is visible
|
||||
# Update slider, current temperature & target temperature
|
||||
- script.execute:
|
||||
id: set_climate
|
||||
current_temp: !lambda "return id(thermostat_embedded).current_temperature;"
|
||||
target_temp: !lambda "return id(thermostat_embedded).target_temperature;"
|
||||
temp_step: !lambda "return int(round(${temp_step}*10));"
|
||||
total_steps: !lambda |-
|
||||
float temp_step = ${temp_step};
|
||||
float temp_offset = ${temp_min};
|
||||
float temp_max = ${temp_max};
|
||||
float total_steps = (temp_max-temp_offset)/temp_step;
|
||||
return int(round(total_steps));
|
||||
slider_val: !lambda |-
|
||||
float temp_step = ${temp_step};
|
||||
float temp_offset = ${temp_min};
|
||||
return int(round((10*id(thermostat_embedded).target_temperature-temp_offset)/temp_step));
|
||||
temp_offset: !lambda "return int(round(${temp_min}*10));"
|
||||
climate_icon: ""
|
||||
embedded_climate: True
|
||||
|
||||
# Update target temp icon
|
||||
- lambda: |-
|
||||
ESP_LOGV("script.addon_climate_update_page_climate", "thermostat_embedded.action=%i", int(id(thermostat_embedded).action));
|
||||
switch (int(id(thermostat_embedded).action)) // CLIMATE_ACTION_OFF = 0, CLIMATE_ACTION_COOLING = 2, CLIMATE_ACTION_HEATING = 3, CLIMATE_ACTION_IDLE = 4, CLIMATE_ACTION_DRYING = 5, CLIMATE_ACTION_FAN = 6
|
||||
{
|
||||
case 0: //CLIMATE_ACTION_OFF
|
||||
ESP_LOGV("script.addon_climate_update_page_climate", "thermostat_embedded.mode=%i", int(id(thermostat_embedded).mode));
|
||||
switch (int(id(thermostat_embedded).mode)) // CLIMATE_MODE_OFF = 0, CLIMATE_MODE_HEAT_COOL = 1, CLIMATE_MODE_COOL = 2, CLIMATE_MODE_HEAT = 3, CLIMATE_MODE_FAN_ONLY = 4, CLIMATE_MODE_DRY = 5, CLIMATE_MODE_AUTO = 6
|
||||
{
|
||||
case 0: //CLIMATE_MODE_OFF
|
||||
id(disp1).set_component_text_printf("climate.target_icon", "%s", "\uFFFF"); // (E424) Don't show icon when off
|
||||
id(disp1).set_component_font_color("climate.target_icon", 35921);
|
||||
break;
|
||||
case 1: //CLIMATE_MODE_HEAT_COOL
|
||||
id(disp1).set_component_text_printf("climate.target_icon", "%s", "\uE069");
|
||||
id(disp1).set_component_font_color("climate.target_icon", 35921);
|
||||
break;
|
||||
case 2: //CLIMATE_MODE_COOL
|
||||
id(disp1).set_component_text_printf("climate.target_icon", "%s", "\uE716");
|
||||
id(disp1).set_component_font_color("climate.target_icon", 1055);
|
||||
break;
|
||||
case 3: //CLIMATE_MODE_HEAT
|
||||
id(disp1).set_component_text_printf("climate.target_icon", "%s", "\uE237");
|
||||
id(disp1).set_component_font_color("climate.target_icon", 64164);
|
||||
break;
|
||||
case 4: //CLIMATE_MODE_FAN_ONLY
|
||||
id(disp1).set_component_text_printf("climate.target_icon", "%s", "\uE20F");
|
||||
id(disp1).set_component_font_color("climate.target_icon", 35921);
|
||||
break;
|
||||
case 5: //CLIMATE_MODE_DRY
|
||||
id(disp1).set_component_text_printf("climate.target_icon", "%s", "\uE58D");
|
||||
id(disp1).set_component_font_color("climate.target_icon", 64704);
|
||||
break;
|
||||
case 6: //CLIMATE_MODE_AUTO
|
||||
id(disp1).set_component_text_printf("climate.target_icon", "%s", "\uEE8D");
|
||||
id(disp1).set_component_font_color("climate.target_icon", 35921);
|
||||
break;
|
||||
}
|
||||
case 2: //CLIMATE_ACTION_COOLING
|
||||
id(disp1).set_component_text_printf("climate.target_icon", "%s", "\uE716");
|
||||
id(disp1).set_component_font_color("climate.target_icon", 1055);
|
||||
break;
|
||||
case 3: //CLIMATE_ACTION_HEATING
|
||||
id(disp1).set_component_text_printf("climate.target_icon", "%s", "\uE237");
|
||||
id(disp1).set_component_font_color("climate.target_icon", 64164);
|
||||
break;
|
||||
case 4: //CLIMATE_ACTION_IDLE
|
||||
id(disp1).set_component_text_printf("climate.target_icon", "%s", "\uE50E"); // mdi:thermometer
|
||||
id(disp1).set_component_font_color("climate.target_icon", 35921);
|
||||
break;
|
||||
case 5: //CLIMATE_ACTION_DRYING
|
||||
id(disp1).set_component_text_printf("climate.target_icon", "%s", "\uE58D");
|
||||
id(disp1).set_component_font_color("climate.target_icon", 64704);
|
||||
break;
|
||||
case 6: //CLIMATE_ACTION_FAN
|
||||
id(disp1).set_component_text_printf("climate.target_icon", "%s", "\uE20F");
|
||||
id(disp1).set_component_font_color("climate.target_icon", 1530);
|
||||
break;
|
||||
}
|
||||
|
||||
# Update buttons bar
|
||||
- lambda: |-
|
||||
ESP_LOGV("script.addon_climate_update_page_climate", "Updating buttons bar");
|
||||
// Hide not supported hotspots
|
||||
id(disp1).hide_component("climate.button01");
|
||||
id(disp1).hide_component("climate.button02");
|
||||
id(disp1).show_component("climate.button03"); //Heat
|
||||
id(disp1).hide_component("climate.button04");
|
||||
id(disp1).hide_component("climate.button05");
|
||||
id(disp1).hide_component("climate.button06");
|
||||
id(disp1).show_component("climate.button07"); //Off
|
||||
// Set buttons colors
|
||||
id(disp1).set_component_font_color("climate.button01_icon", 10597);
|
||||
id(disp1).set_component_font_color("climate.button02_icon", 10597);
|
||||
id(disp1).set_component_font_color("climate.button03_icon", (id(thermostat_embedded).mode==climate::CLIMATE_MODE_HEAT) ? 64164 : 48631);
|
||||
id(disp1).set_component_font_color("climate.button04_icon", 10597);
|
||||
id(disp1).set_component_font_color("climate.button05_icon", 10597);
|
||||
id(disp1).set_component_font_color("climate.button06_icon", 10597);
|
||||
id(disp1).set_component_font_color("climate.button07_icon", (id(thermostat_embedded).mode==climate::CLIMATE_MODE_OFF) ? 35921 : 48631);
|
||||
- lambda: ESP_LOGV("script.addon_climate_update_page_climate", "Finished");
|
||||
|
||||
switch:
|
||||
##### PHYSICAL SWITCH 0 (Dummy) - Used when relay is not set #####
|
||||
- name: ${device_name} Relay 0 (dummy)
|
||||
platform: template
|
||||
id: relay_0
|
||||
lambda: !lambda return false;
|
||||
internal: true
|
||||
optimistic: true
|
||||
Reference in New Issue
Block a user