How to set up a schedule for generic_thermostat?

I’m having loads of fun here, but it’s taking a real concerted effort to understand sometimes. I’m doing my best to pour over documentation and forum posts before I do ask questions. So appolgies in advance!

//Edit: This first post isn’t relevant because i’ve moved to a generic_thermostat, and climate integration.

I have an automation as below:

main_room_heater_control.yaml

# Use the inputs from frontend to
# turn the heater plug on and off 
# if set to auto

-  id: '82734629756294'
   alias: Main Room Heater Control Off
   trigger:
     platform: numeric_state
     entity_id: sensor.temperature_7
     above: "{{ states('input_number.living_room_target_temp')|float }}"
     for:
       minutes: 30
   condition:
     condition: state
     entity_id: input_select.living_room_heater
     state: 'Auto'
   action:
     service: switch.turn_off
     entity_id: switch.salus_smart_plug_meter_1
     
-  id: '102301247234'
   alias: Main Room Heater Control On
   trigger:
     platform: numeric_state
     entity_id: sensor.temperature_7|float
     below: "{{ states('input_number.living_room_target_temp')|float }}"
     for:
       minutes: 30
   condition:
     condition: state
     entity_id: input_select.living_room_heater
     state: 'Auto'
   action:
     service: switch.turn_on
     entity_id: switch.salus_smart_plug_meter_1

I usually get pretty far by validating my errors as I go, but when I check config, this now shows:

Configuration invalid
Invalid config for [automation]: expected float for dictionary value @ data['trigger'][0]['above']. Got None. (See ?, line ?). 
Invalid config for [automation]: expected float for dictionary value @ data['trigger'][0]['below']. Got None. (See ?, line ?). 

I’m not too sure what I need to change now :thinking:

I also think I should be using templates, but i thought i’d try and make this work first before diving in even deeper :smiley:

No sooner do I post this, than I realise there is something prebuilt:

I’ll read these docs first and come back with questions!

Went back after dinner, and set it up. That was all rather simple actually! (see below).

Now i’m wondering the best way to tackle an automation based on times and working days that are set in the front end, I have input_booleans and times setup as I envisage they should work?

I think it would be good also if I can populate the workday integration from these selections?

I use the generic thermostat too but I also have a python scheduler…

#########################################################################################

#

# Originally created by ABMANTIS - https://ledstripsandcode.blogspot.com/2018/11/simple-thermostat-scheduler-in-home.html

#

# Modified to suit my needs - KeithH666

#

#########################################################################################

# import HA input_numbers for WeekdayMorning StartHour/StartMinute - FinishHour/FinishMinute

# import HA input_numbers for WeekdayEvening StartHour/StartMinute - FinishHour/FinishMinute

# import HA input_numbers for SatMorning StartHour/StartMinute - FinishHour/FinishMinute

# import HA input_numbers for SatEvening StartHour/StartMinute - FinishHour/FinishMinute

# import HA input_numbers for SundayMorning StartHour/StartMinute - FinishHour/FinishMinute

# import HA input_numbers for SundayEvening StartHour/StartMinute - FinishHour/FinishMinute

wmsh = int(float(hass.states.get('input_number.wmsh').state))

wmsm = int(float(hass.states.get('input_number.wmsm').state))

wmfh = int(float(hass.states.get('input_number.wmfh').state))

wmfm = int(float(hass.states.get('input_number.wmfm').state))

wesh = int(float(hass.states.get('input_number.wesh').state))

wesm = int(float(hass.states.get('input_number.wesm').state))

wefh = int(float(hass.states.get('input_number.wefh').state))

wefm = int(float(hass.states.get('input_number.wefm').state))

satmsh = int(float(hass.states.get('input_number.satmsh').state))

satmsm = int(float(hass.states.get('input_number.satmsm').state))

satmfh = int(float(hass.states.get('input_number.satmfh').state))

satmfm = int(float(hass.states.get('input_number.satmfm').state))

satesh = int(float(hass.states.get('input_number.satesh').state))

satesm = int(float(hass.states.get('input_number.satesm').state))

satefh = int(float(hass.states.get('input_number.satefh').state))

satefm = int(float(hass.states.get('input_number.satefm').state))

sunmhs = int(float(hass.states.get('input_number.sunmhs').state))

sunmms = int(float(hass.states.get('input_number.sunmms').state))

sunmfh = int(float(hass.states.get('input_number.sunmfh').state))

sunmfm = int(float(hass.states.get('input_number.sunmfm').state))

sunehs = int(float(hass.states.get('input_number.sunehs').state))

sunems = int(float(hass.states.get('input_number.sunems').state))

sunefh = int(float(hass.states.get('input_number.sunefh').state))

sunefm = int(float(hass.states.get('input_number.sunefm').state))

# Import HA Booleans for override/heating away/heating on

# climate override is for when I'm home earlier then expected or am staying up later then expected

climate_override = hass.states.get('input_boolean.climate_override').state

# heating_away is when I'm away at work or just elsewhere

heating_away     = hass.states.get('input_boolean.heat_away').state

# heating_on is an override for the whole scheduler - such as in summer it acts to turn it all off

heating_on       = hass.states.get('input_boolean.heating_on').state

# The next 3 are the temperatures for each room 

temp_heat_livingr = int(float(hass.states.get('input_number.heat_home_livingr').state))

temp_heat_bathr   = int(float(hass.states.get('input_number.heat_home_bathr').state))

temp_heat_hall    = int(float(hass.states.get('input_number.heat_home_hall').state))

# Override for the away temp

temp_heat_away   = int(float(hass.states.get('input_number.heat_away').state))

WEEK_SCHEDULE = [

    [datetime.time(00,00), datetime.time(00,30)],    

    [datetime.time((wmsh),(wmsm)), datetime.time((wmfh),(wmfm))],    

    [datetime.time((wesh),(wesm)), datetime.time((wefh),(wefm),59)]   

]

SAT_SCHEDULE = [

    [datetime.time(00,00), datetime.time(00,30)],

    [datetime.time((satmsh),(satmsm)), datetime.time((satmfh),(satmfm))],

    [datetime.time((satesh),(satesm)), datetime.time((satefh),(satefm), 59)]

]

SUN_SCHEDULE = [

    [datetime.time(00,00), datetime.time(00,30)],

    [datetime.time((sunmhs),(sunmms)), datetime.time((sunmfh),(sunmfm))],

    [datetime.time((sunehs),(sunems)), datetime.time((sunefh),(sunefm), 59)]

]

# Initially setup target temps from input_numbers

TEMP_HIGH_LIVINGR = temp_heat_livingr

TEMP_HIGH_BATHR   = temp_heat_bathr

TEMP_HIGH_HALL    = temp_heat_hall

TEMP_LOW_LIVINGR  = temp_heat_away

TEMP_LOW_BATHR    = temp_heat_away

TEMP_LOW_HALL     = temp_heat_away

# Create the climate entities

climate_entity  = 'climate.lr_main'    # set to your thermostat entity

climate_entity1 = 'climate.lr_backup'  # set to your thermostat entity

climate_entity2 = 'climate.bathroom'   # set to your thermostat entity

climate_entity3 = 'climate.hall'       # set to your thermostat entity

# if heating_on (ie autumn/winter/spring)

if heating_on == 'on':

    # test output logging

    #hass.services.call('system_log', 'write', {'message': "heating_on == on"})

    if heating_away == 'on':

        # set  preset_mode to away - climate will use the away temp it was initially set to 

        hass.services.call('climate', 'set_preset_mode', {'entity_id': climate_entity,  'preset_mode': 'away'})

        hass.services.call('climate', 'set_preset_mode', {'entity_id': climate_entity1, 'preset_mode': 'away'})

        hass.services.call('climate', 'set_preset_mode', {'entity_id': climate_entity2, 'preset_mode': 'away'})

        hass.services.call('climate', 'set_preset_mode', {'entity_id': climate_entity3, 'preset_mode': 'away'})

        #hass.services.call('system_log', 'write', {'message': "heating_away == on"})

        exit()

    # if climate override is on 

    if climate_override == 'on':

        TEMP_LOW_LIVINGR = temp_heat_livingr

        TEMP_LOW_BATHR   = temp_heat_bathr

        TEMP_LOW_BATHR   = temp_heat_hall

    # get the current temp for each room

    current_lr_temp       = hass.states.get(climate_entity).attributes['temperature']

    current_bathroom_temp = hass.states.get(climate_entity2).attributes['temperature']

    current_hall_temp     = hass.states.get(climate_entity3).attributes['temperature']

    # get current date and time

    now = datetime.datetime.now().time()

    # determine which scedule is appropriate

    if datetime.datetime.now().date().weekday() < 5: # 0 - 4 Mon-Fri 5 Sat 6 Sun

        current_schedule = WEEK_SCHEDULE

    elif datetime.datetime.now().date().weekday() == 5:

        current_schedule = SAT_SCHEDULE

    else:

        current_schedule = SUN_SCHEDULE

    # determine if we want the heating on for this time in the schedule

    in_high_time = False

    for high_time in current_schedule:

        start = high_time[0]

        end = high_time[1]

        

        if start <= now <= end:        

            in_high_time = True

            break

    # override the scheduler if needed

    if climate_override == 'on':

        in_high_time = True

    new_temp_lr = TEMP_HIGH_LIVINGR if in_high_time else TEMP_LOW_LIVINGR 

    if new_temp_lr != current_lr_temp:

        # set the thermostat target temperature/presetmode/hvac mode and turn on.

        hass.services.call('climate', 'turn_on', {'entity_id': climate_entity})

        hass.services.call('climate', 'set_preset_mode', {'entity_id': climate_entity,  'preset_mode': "none"})

        hass.services.call('climate', 'set_hvac_mode', {'entity_id': climate_entity,  'hvac_mode': "heat"})

        hass.services.call('climate', 'set_temperature', {'entity_id': climate_entity,  'temperature': new_temp_lr, 'hvac_mode': "heat"})

        hass.services.call('climate', 'turn_on', {'entity_id': climate_entity1})

        hass.services.call('climate', 'set_preset_mode', {'entity_id': climate_entity1,  'preset_mode': "none"})

        hass.services.call('climate', 'set_hvac_mode', {'entity_id': climate_entity1,  'hvac_mode': "heat"})

        hass.services.call('climate', 'set_temperature', {'entity_id': climate_entity1, 'temperature': new_temp_lr, 'hvac_mode': "heat"})

        # also send a notification so that I know that it changed the temperature.

        hass.services.call('script', 'ariela_send_notification', {'message': 'Changing Livingroom temperature to {} (was at {})'.format(new_temp_lr, current_lr_temp)})    

    new_temp_br = TEMP_HIGH_BATHR if in_high_time else TEMP_LOW_BATHR

    if new_temp_br != current_bathroom_temp:

        # set the thermostat target temperature/presetmode/hvac mode and turn on.

        hass.services.call('climate', 'turn_on', {'entity_id': climate_entity2})

        hass.services.call('climate', 'set_preset_mode', {'entity_id': climate_entity2,  'preset_mode': "none"})

        hass.services.call('climate', 'set_hvac_mode', {'entity_id': climate_entity2,  'hvac_mode': "heat"})

        hass.services.call('climate', 'set_temperature', {'entity_id': climate_entity2, 'temperature': new_temp_br, 'hvac_mode': "heat"})

        # also send a notification so that I know that it changed the temperature.

        hass.services.call('script', 'ariela_send_notification', {'message': 'Changing Bathroom temperature to {} (was at {})'.format(new_temp_br, current_bathroom_temp)})

        

    new_temp_hall = TEMP_HIGH_HALL if in_high_time else TEMP_LOW_HALL

    if new_temp_hall != current_hall_temp:

        # set the thermostat target temperature/presetmode/hvac mode and turn on.

        hass.services.call('climate', 'turn_on', {'entity_id': climate_entity3})

        hass.services.call('climate', 'set_preset_mode', {'entity_id': climate_entity3,  'preset_mode': "none"})

        hass.services.call('climate', 'set_hvac_mode', {'entity_id': climate_entity3,  'hvac_mode': "heat"})

        hass.services.call('climate', 'set_temperature', {'entity_id': climate_entity3, 'temperature': new_temp_hall, 'hvac_mode': "heat"})

        # also send a notification so that I know that it changed the temperature.

        hass.services.call('script', 'ariela_send_notification', {'message': 'Changing Hall temperature to {} (was at {})'.format(new_temp_hall, current_hall_temp)})

else:

    # if summer turn off heating

    hass.services.call('climate', 'turn_off', {'entity_id': climate_entity})

    hass.services.call('climate', 'turn_off', {'entity_id': climate_entity1})

    hass.services.call('climate', 'turn_off', {'entity_id': climate_entity2})

    hass.services.call('climate', 'turn_off', {'entity_id': climate_entity3})

    # test output logging

    #hass.services.call('system_log', 'write', {'message': "heating_on == off"})

I have weekday morning/evening/start/finish input sliders as well as sat and sun ones as I work most sats, I’ve also added an override and spring/winter/autumn settings.

You might find it useful.

2 Likes

Wow thanks! I will pour over this next. Its way over my head coding python to do this right now. I think I really need to bite the bullet and take a course and take python and coding seriously…

ABMANTIS wrote the original code, see Simple thermostat scheduler in Home Assistant

So you might want to look at the simpler version first :slight_smile:

There is also a thread on here somewhere which talks about it…

1 Like

Hey Alexdood

Was just wondering if you got the heating scheduler up and running? That screenshot looks exactly like what I would like to make for my TVRs. Any help or guidance will be much appreciated.

Thanks in advance, Kal

Hi @keithh666 thanks for posting this. Im not to good at programming but slowly learning.

Is it posable to use the input_datetime in home assistant instead of separate input_numbers?

With my little knowledge in python, it seems the week_schedule and weekend_schedule create a list (I think) and obviously input_datetime will create a time or even a timestamp.

How would I adapt the code or would it be too involved please.

Thank you.

Thinking about this today, could we use the input_datetime attributes, something like:

wmsh = int(float(hass.states.get(state_attr('input_datetime.week_morning_start','hour'))))

Ive got no idea if the above method will work.

I now use a scheduler add on to set my heating, as there are now two add-on’s for this and they are much more efficient.

@keithh666 , I didn’t find any of those.
Would you mind telling which one you’re using?

edit
found and installed HACS: https://github.com/hacs/integration
and scheduler-component https://github.com/nielsfaber/scheduler-component
haven’t tested it yet though

That’s what I use but also get the GitHub - nielsfaber/scheduler-card: HA Lovelace card for control of scheduler entities addon for lovelace.

1 Like

Is it possible to have a guide on how to implement this code?

I haven’t used that code in years as schedulers have ben implemented, so I use that instead :slight_smile: