Heaty will die, Schedy be born!

Schedy will die, scheduler-card be born!

Hi,
a few days ago I started to use Shedy for my heating system. The config looks like this:

schedy: 
  module: hass_apps_loader
  class: SchedyApp

  expression_environment: | 
     def heating_mode():
        return state("input_select.heating_mode")
     def heating_season():
        return state("input_select.heating_season")
 
  actor_templates:
    default:
    #delta: 0.0
      off_temp: 7
      supports_hvac_modes: false

  schedule_prepend:
  # - x: "Mark(7, Mark.OVERLAY) if not is_empty(filter_entities('binary_sensor', state='on', window_room=room_name)) else Next()"

  schedule_append:
    - v: 7

  schedule_snippets:
    bedroom:
    - { v: 17, start: "07:00", end: "20:00" }
    - { v: 21, start: "20:00", end: "22:00" }
    - { v: 20, start: "22:00", end: "07:00" }
    homeOffice: 
    - { v: 20, start: "00:00", end: "08:00" }
    - { v: 22, start: "08:00", end: "20:00" }
    - { v: 20, start: "20:00", end: "00:00" }
    holiday: 
    - { v: 17, start: "00:00", end: "00:00" }
    default: 
    - { v: 19, start: "00:00", end: "00:00" }
    livingroom:
    - { v: 18, start: "00:00", end: "06:00" }
    - { v: 22, start: "06:00", end: "08:00" }
    - { v: 18, start: "08:00", end: "16:00" }
    - { v: 22, start: "16:00", end: "00:00" }
    bathroom:
    - { v: 18, start: "00:00", end: "06:00" }
    - { v: 24, start: "06:00", end: "08:00" }
    - { v: 18, start: "08:00", end: "20:00" }
    - { v: 24, start: "20:00", end: "00:00" }

  watched_entities:
  - input_select.heating_mode
  - input_select.heating_season
 
  rooms:
    living:
      #friendly_name: ...
      allow_manual_changes: true
      #replicate_changes: true
      rescheduling_delay: 120
      actors:
        climate.devolo_thermostat_09356_6:  #Wohnzimmerbalkontür
        climate.devolo_thermostat_09356:    #Wohnzimmerfenster
      schedule:
      - weekdays: 1-7
        rules:
        - x: "7 if is_on('binary_sensor.wohnzimmerfenster') else Next()"
        - x: "7 if is_on('binary_sensor.wohnzimmerbalkontur') else Next()"
        - x: "7 if is_on('binary_sensor.kuchenfenster') else Next()"
        - x: "IncludeSchedule(schedule_snippets['livingroom'])"
        - x: "IncludeSchedule(schedule_snippets['holiday']) if heating_mode() == 'Holiday' else Next()"
      watched_entities:
          - binary_sensor.wohnzimmerfenster
          - binary_sensor.wohnzimmerbalkontur
          - binary_sensor.kuchenfenster
          
    bed:
      #friendly_name: ...
      allow_manual_changes: true
      #replicate_changes: true
      rescheduling_delay: 120
      actors:
        climate.devolo_thermostat_09356_7:
      schedule:
      - weekdays: 1-7
        rules:
        - x: "7 if is_on('binary_sensor.schlafzimmerfenster_rechts') else Next()"
        - x: "7 if is_on('binary_sensor.schlafzimmerfenster_links') else Next()"
        - x: "IncludeSchedule(schedule_snippets['bedroom'])"
        - x: "IncludeSchedule(schedule_snippets['holiday']) if heating_mode() == 'Holiday' else Next()"
      watched_entities:
        - binary_sensor.schlafzimmerfenster_rechts
        - binary_sensor.schlafzimmerfenster_links

    guest:
      #friendly_name: ...
      allow_manual_changes: true
      #replicate_changes: true
      rescheduling_delay: 120
      actors:
        climate.devolo_thermostat_09356_4:
      schedule:
      - weekdays: 1-7
        rules:
        - x: "7 if is_on('binary_sensor.gastezimmerfenster_links') else Next()"
        - x: "IncludeSchedule(schedule_snippets['default'])"
        - x: "IncludeSchedule(schedule_snippets['holiday']) if heating_mode() == 'Holiday' else Next()"
      watched_entities:
        - binary_sensor.gastezimmerfenster_links

    buero:
      #friendly_name: ...
      allow_manual_changes: true
      #replicate_changes: true
      rescheduling_delay: 120
      actors:
        climate.devolo_thermostat_09356_2:
      schedule:
      - weekdays: 1-7
        rules:
        - x: "7 if is_on('binary_sensor.burobalkontur') else Next()"
        - x: "IncludeSchedule(schedule_snippets['default'])"
        - x: "IncludeSchedule(schedule_snippets['homeOffice']) if heating_mode() == 'HomeOffice' else Next()"
        - x: "IncludeSchedule(schedule_snippets['holiday']) if heating_mode() == 'Holiday' else Next()"
      watched_entities:
        - binary_sensor.burobalkontur
      
    badezimmer:
      #friendly_name: ...
      allow_manual_changes: true
      #replicate_changes: true
      rescheduling_delay: 120
      actors:
        climate.devolo_thermostat_09356_3:
      schedule:
      - weekdays: 1-7
        rules:
        - x: "IncludeSchedule(schedule_snippets['bathroom'])"
        - x: "IncludeSchedule(schedule_snippets['holiday']) if heating_mode() == 'Holiday' else Next()"
      watched_entities:
      
    vorzimmer:
      #friendly_name: ...
      allow_manual_changes: true
      #replicate_changes: true
      rescheduling_delay: 120
      actors:
        climate.devolo_thermostat_09356_5:
      schedule:
      - weekdays: 1-7
        rules:
        - x: "7 if is_on('binary_sensor.eingangstur') else Next()"
        - x: "IncludeSchedule(schedule_snippets['default'])"
        - x: "IncludeSchedule(schedule_snippets['holiday']) if heating_mode() == 'Holiday' else Next()"
      watched_entities:
        - binary_sensor.eingangstur

  statistics:

Now I get in the log window the following warnings:

2021-06-06 20:59:12.449645 WARNING schedy: schedy: Entity input_select.heating_season not found in namespace default
2021-06-06 20:59:12.439284 WARNING schedy: schedy: Entity input_select.heating_mode not found in namespace default

Where do I have to define the input select? If I look at the tutorial of Shedy I think it should look like this:

input_select:
  heating_mode:
    name: Heating Mode
    options:
    - Default
    - HomeOffice
    - Holiday

But where I have to add this?

BR

It is easy. The input_select part just belongs into your main configuration.yaml. Do not forget to restart to make it available.

BR

Thanks! This I already tried before, but forgot to restart HomeAssistant :see_no_evil:

THANK YOU! :+1:

Hi thanks to your @GAtti and @Reynald post I have a working generic2 version for roller shutters driven by shelly2

  module: hass_apps_loader
  class: SchedyApp
  actor_type: generic2
  actor_templates:
    default:
      template: cover
    cover:
      attributes:
        - attribute: state
      values:
        - value: ["open"]
          calls:
          - service: cover.set_cover_position
            data:
              position: 100
            include_entity_id: true
        - value: ["closed"]
          calls:
          - service: cover.set_cover_position
            data:
              position: 0
            include_entity_id: true
  rescheduling_delay: 30

And of course a working one for generic (what I was starting from)

  module: hass_apps_loader
  class: SchedyApp
  actor_type: generic
  actor_templates:
    default:
      template: cover
    cover:
      attributes:
        - attribute: state
          values:
            "open":
              service: cover.set_cover_position
              service_data: {"position":100}
              include_entity_id: true
              value_parameter: null
            "closed":
              service: cover.set_cover_position
              service_data: {"position":0}
              include_entity_id: true
              value_parameter: null
      short_values:
        - ['closed']
        - ['open']
      send_retries: 3
  rescheduling_delay: 30

I hope this helps you or others. I will try to extend it to a full working schedule. Took me some hours to get to this working version.

1 Like

@Styx85 Would it be possible to publish all your code for the shutters planning?

Trying to get started with schedy. Got everything up and running.
Working through getting my first config file setup with my evohome thermostats. I’m using the evohome_cc integration through the nanocul and have tried to use my “zones” as thermostats.
Unfortunately in the logs I get the following error:

WARNING schedy: !!! [R:woonkamer] [A:climate.woonkamer_2] Thermostat doesn't seem to support the HVAC mode off, supported modes are: ['auto', 'heat']. Please check your config!

The mode “off” doesn’t exist for individual zones. Has anybody here had to deal with this issue and how did you solve it?

ADAX heater panels with Schedy

Dear All,
A rookie looking for some help here in implementing ADAX wifi heaters in Schedy.
AppDaemon 4 (0.7.0).
My first approach is to turn two heaters on and off with Schedy.

heating:
  module: hass_apps_loader
  class: SchedyApp

  actor_type: thermostat

  schedule_append:
  - v: "OFF"

  rooms:
    kitchen:
      actors:
        climate.kitchen1:
        climate.kitchen2:
      schedule:
        - v: 20
          rules:
          - { start: "22:15:00", end: "22:16:00" }

Actor climate.kitchen1 acting accordingly to the command and from OFF state turns the unit into 20 °C, and turns OFF.
However, climate.kitchen2 changes state from OFF to 5 °C (minimum temperature) and turns OFF.
Is it something wrong in my syntax?

here’s the log:

2021-09-20 22:42:12.510669 INFO heating: *** Thank you very much and enjoy schedy!
2021-09-20 22:42:12.514905 INFO heating: *** 
2021-09-20 22:42:12.533896 INFO heating: --- Actor type is: 'thermostat'
2021-09-20 22:42:12.575273 INFO heating: --> [R:kitchen] [A:climate.kitchen1] Received value of OFF.
2021-09-20 22:42:12.613665 INFO heating: --> [R:kitchen] [A:climate.kitchen2] Received value of OFF.
2021-09-20 22:42:12.751209 INFO heating: *** Initialization done.
2021-09-20 22:42:12.756237 INFO AppDaemon: App initialization complete
2021-09-20 22:44:10.747817 WARNING heating: ------------------------------------------------------------
2021-09-20 22:44:10.749067 WARNING heating: Unexpected error in worker for App heating:
2021-09-20 22:44:10.750465 WARNING heating: Worker Ags: {'id': 'c6172df449cb4bc0a0600a2d734e4f75', 'name': 'heating', 'objectid': 'f39d2c4577714dcfa3e02b0c0e36b136', 'type': 'scheduler', 'function': <bound method Room._scheduling_timer_cb of <Room R:kitchen>>, 'pin_app': True, 'pin_thread': 0, 'kwargs': {'interval': 86400, '__thread_id': 'thread-0'}}
2021-09-20 22:44:10.751791 WARNING heating: ------------------------------------------------------------
2021-09-20 22:44:10.756151 WARNING heating: Traceback (most recent call last):
  File "/usr/lib/python3.9/site-packages/appdaemon/threading.py", line 890, in worker
    funcref(self.AD.sched.sanitize_timer_kwargs(app, args["kwargs"]))
  File "/usr/lib/python3.9/site-packages/hass_apps/schedy/room.py", line 50, in wrapper
    result = handler(self, *args, **kwargs)
  File "/usr/lib/python3.9/site-packages/hass_apps/schedy/room.py", line 203, in _scheduling_timer_cb
    self.apply_schedule()
  File "/usr/lib/python3.9/site-packages/hass_apps/schedy/room.py", line 50, in wrapper
    result = handler(self, *args, **kwargs)
  File "/usr/lib/python3.9/site-packages/hass_apps/schedy/room.py", line 408, in apply_schedule
    self.set_value(new_scheduled_value, force_resend=force_resend)
  File "/usr/lib/python3.9/site-packages/hass_apps/schedy/room.py", line 587, in set_value
    changed |= actor.set_value(value, force_resend=force_resend)[0]
  File "/usr/lib/python3.9/site-packages/hass_apps/schedy/actor/base.py", line 285, in set_value
    self._resending_cb({"left_tries": self.cfg["send_retries"] + 1})
  File "/usr/lib/python3.9/site-packages/hass_apps/schedy/room.py", line 50, in wrapper
    result = handler(self, *args, **kwargs)
  File "/usr/lib/python3.9/site-packages/hass_apps/schedy/actor/base.py", line 93, in _resending_cb
    self.do_send()
  File "/usr/lib/python3.9/site-packages/hass_apps/schedy/actor/thermostat.py", line 323, in do_send
    self.app.call_service(
  File "/usr/lib/python3.9/site-packages/appdaemon/utils.py", line 197, in inner_sync_wrapper
    f = run_coroutine_threadsafe(self, coro(self, *args, **kwargs))
  File "/usr/lib/python3.9/site-packages/appdaemon/utils.py", line 317, in run_coroutine_threadsafe
    result = future.result(self.AD.internal_function_timeout)
  File "/usr/lib/python3.9/concurrent/futures/_base.py", line 447, in result
    raise TimeoutError()
concurrent.futures._base.TimeoutError
2021-09-20 22:44:10.757263 WARNING heating: ------------------------------------------------------------
2021-09-20 22:44:10.763868 WARNING AppDaemon: callback _scheduling_timer_cb() in heating has now completed
2021-09-20 22:44:10.798353 INFO heating: --> [R:kitchen] [A:climate.kitchen1] Received value of 5.0��.
2021-09-20 22:44:10.803570 INFO heating: --- [R:kitchen] Propagating the change to all actors in the room.
2021-09-20 22:44:20.821214 WARNING heating: ------------------------------------------------------------
2021-09-20 22:44:20.822652 WARNING heating: Unexpected error in worker for App heating:
2021-09-20 22:44:20.824378 WARNING heating: Worker Ags: {'id': 'b46765e628ff4f9bbf7b7ebd47108c88', 'name': 'heating', 'objectid': 'f39d2c4577714dcfa3e02b0c0e36b136', 'type': 'state', 'function': <bound method ActorBase._state_cb of <Actor A:climate.kitchen1>>, 'attribute': 'all', 'entity': 'climate.kitchen1', 'new_state': {'entity_id': 'climate.kitchen1', 'state': 'heat', 'attributes': {'hvac_modes': ['heat', 'off'], 'min_temp': 5, 'max_temp': 35, 'target_temp_step': 1, 'current_temperature': 21.0, 'temperature': 5.0, 'friendly_name': 'kitchen1', 'icon': 'mdi:radiator', 'supported_features': 1}, 'last_changed': '2021-09-20T20:44:00.729345+00:00', 'last_updated': '2021-09-20T20:44:00.729345+00:00', 'context': {'id': '31e338592d7a109e153f4f093b7cefa3', 'parent_id': None, 'user_id': '215b58604ee44303b618703d9f3a3e83'}}, 'old_state': {'entity_id': 'climate.kitchen1', 'state': 'off', 'attributes': {'hvac_modes': ['heat', 'off'], 'min_temp': 5, 'max_temp': 35, 'target_temp_step': 1, 'current_temperature': 21.0, 'temperature': 0.0, 'friendly_name': 'kitchen1', 'icon': 'mdi:radiator-off', 'supported_features': 1}, 'last_changed': '2021-09-20T20:05:03.091135+00:00', 'last_updated': '2021-09-20T20:43:01.399772+00:00', 'context': {'id': '690973cb6120319f460a6a63f38f67c0', 'parent_id': None, 'user_id': None}}, 'pin_app': True, 'pin_thread': 0, 'kwargs': {'attribute': 'all', '__thread_id': 'thread-0'}}
2021-09-20 22:44:20.826243 WARNING heating: ------------------------------------------------------------
2021-09-20 22:44:20.828411 WARNING heating: Traceback (most recent call last):
  File "/usr/lib/python3.9/site-packages/appdaemon/threading.py", line 903, in worker
    funcref(
  File "/usr/lib/python3.9/site-packages/hass_apps/schedy/room.py", line 50, in wrapper
    result = handler(self, *args, **kwargs)
  File "/usr/lib/python3.9/site-packages/hass_apps/schedy/actor/base.py", line 130, in _state_cb
    self.events.trigger("value_changed", self, new_value)
  File "/usr/lib/python3.9/site-packages/observable/core.py", line 133, in trigger
    callback(*args, **kw)
  File "/usr/lib/python3.9/site-packages/hass_apps/schedy/room.py", line 555, in notify_value_changed
    self.set_value(value)
  File "/usr/lib/python3.9/site-packages/hass_apps/schedy/room.py", line 587, in set_value
    changed |= actor.set_value(value, force_resend=force_resend)[0]
  File "/usr/lib/python3.9/site-packages/hass_apps/schedy/actor/base.py", line 285, in set_value
    self._resending_cb({"left_tries": self.cfg["send_retries"] + 1})
  File "/usr/lib/python3.9/site-packages/hass_apps/schedy/room.py", line 50, in wrapper
    result = handler(self, *args, **kwargs)
  File "/usr/lib/python3.9/site-packages/hass_apps/schedy/actor/base.py", line 93, in _resending_cb
    self.do_send()
  File "/usr/lib/python3.9/site-packages/hass_apps/schedy/actor/thermostat.py", line 319, in do_send
    self.app.call_service(
  File "/usr/lib/python3.9/site-packages/appdaemon/utils.py", line 197, in inner_sync_wrapper
    f = run_coroutine_threadsafe(self, coro(self, *args, **kwargs))
  File "/usr/lib/python3.9/site-packages/appdaemon/utils.py", line 317, in run_coroutine_threadsafe
    result = future.result(self.AD.internal_function_timeout)
  File "/usr/lib/python3.9/concurrent/futures/_base.py", line 447, in result
    raise TimeoutError()
concurrent.futures._base.TimeoutError
2021-09-20 22:44:20.829545 WARNING heating: ------------------------------------------------------------
2021-09-20 22:44:20.836719 WARNING AppDaemon: callback _state_cb() in heating has now completed

Any help is highly appreciated.
Thank you in advance.

My final setup : My Canaletto | Home Assistant & Schedy, encore...

And YAML : https://github.com/mycanaletto/hass-mondon

Hello @roschi

I understood your wish to manage air conditioners in automatic mode: hvac_mode_on: heat_cool and I think there was a lot of discussion on this subject.

I put my approach in a configuration where the user can’t touch the YAML code, he only uses Lovelace.

This way of doing things works very well in summer or winter, but in spring and autumn it often leads to the air conditioner running either cold or hot, at a time when it should just be turned off and should not consume for nothing.

I have tried to get around this with rules, but it complicates and slows down.

I know you don’t have much time, but what would be nice would be to be able to change the value of hvac_mode_on: to heat or cool by an input_select: or an event that would allow via a script to change the template.

The other solution I thought of is to make two rooms, ac_cool: and ac_heat:, but it seems a bit extreme.

Still in my interface approach, I’m interested in ideas.

Merci :wink:

Started the heating season. Experienced a problem.

2021-09-28 13:11:37.249112 WARNING schedy_heating: !!! [R:wohnesszimmer] [A:climate.wohnzimmer_heizung_rechts] The value None of attribute 'temperature' is no valid temperature.

I changed the z-wave integration. So maybe the attributes changed. These are the attributes of the thermostat.

hvac_modes: off, heat
min_temp: 7
max_temp: 35
preset_modes: none, Energy heat, Full power
current_temperature: 19.5
temperature: null
preset_mode: none
friendly_name: wohnzimmer_heizung_links
supported_features: 17

Does anyone know this problem? Can schedy accept “null” oder can I change the attribute to “0” instead of “null”?

Is it somehow possible to use an input_datetime as start/end for the schedule?

Something like this:

      schedule:
      - x: state('input_number.climate_work_comfort')
        rules:
        - x: "Next() if state('input_boolean.vacation') == 'off' else IncludeSchedule(schedule_snippets['vacation_work'])"
        - weekdays: 1-5
          rules:
          - { start: state('input_number.work_start'), end: state('input_number.work_end') }
        - weekdays: 6-7
          rules:
          - { start: state('input_number.weekend_start'), end: state('input_number.weekend_end') }

It’s not that simple… Look at what I wrote on my blog, it will give you some ideas on what is possible to interface schedules…

Hello, can you share the code of one of your lovelace card.
I try to configure but with no result.

I have updated on this repo

PS : if you prefer in french it’s better here :

Hello, I’ve got a question regarding Schedy configuration:
Is it possible to use a variable (like a input_number from HA) for the rescheduling_delay?

If I write something like:
rescheduling_delay: "state('input_number.rescheduling_delay')"

Appdeamon comes with the following error:

ERROR schedy_heating: !!! Configuration error: expected float for dictionary value @ data[‘rooms’][‘wohnzimmer’][‘rescheduling_delay’]. Got “state(‘input_number.rescheduling_delay’)”

Would be nice if someone could help me! Thanks!

@tdon I don’t think @roschi has planned for that, but it’s easy to bypass with a script…

script:
  heating_antoine_boost:
    alias: Boost
    icon: mdi:timer-outline
    sequence:
    - event: schedy_set_value
      event_data:
        app_name: schedy_heating
        room: chambre_antoine
        v: '{{ states.input_number.heating_antoine_temperature_boost.state }}'
        rescheduling_delay: '{{ states.input_number.heating_antoine_time_boost.state }}'

Is it possible to parse an expression into the start/end times as well as the start day/month
I am wanting to use the return value from a python function from the expression environment

After some extra reading and testing, i’ve seen you cant dynamically set start and end times.
But i can set the times to entities.

Now im having issues with the expression for the rules.
I want it to run on the exact time as well as the exact date but i cant get the date part to work.

            - x: "state('input_number.seg1_temp') if time.hour >= float(state('input_number.seg1_starthour')) and time.hour <= float(state('input_number.seg1_endhour')) and datetime.now().day == float(state('input_number.seg1_day')) and datetime.now().month == float(state('input_number.seg1_month')) else Next()"

I get the error that datetime.now() is not a function

The 2 are incomparable (I use both). Schedy does so much more and deserves a place in the core.

2 Likes