Heaty will die, Schedy be born!

Yes, that’s correct. Also added this to my previous post.

Oh! I understand now.
I keep seeing sub_schedule, and thinking of an included schedule.
Right - so the temperature is 20, between 7am and 9am, and then 12pm to 10pm, if the switch is on. And 17 outside those times.

OFF, if the switch is off.

Is that right?

Exactly.

FWIW: I just noticed that my wording was a bit inaccurate, only start, end and v of inner rules replace those of outer rules. The constraints (weekdays, months, years etc.) are combined by a logical AND instead, so a rule like this would never match:

- months: 1-3
  rules:
  - { v: 20, months: 4 }
1 Like

Aah, and a static sub-schedule is no different than using IncludeSchedule() from a processing point of view, in fact IncludeSchedule() dynamically inserts a rule like this at evaluation time, right after the rule that returned the IncludeSchedule():

- rules:
  - <rule 1 of included schedule>
  - <rule 2 of included schedule>
  - ...

Thanks roschi, got it!

About the indention issue: This might be a browser issue; at least I am getting a single rogue space character in front of
- v: "OFF"

This also permits cross-schedule inheriting, which allows for creating quite dynamic schedule snippets that inherit the actual value from the room’s context:

- v: 20
  rules:
  - x: "IncludeSchedule(schedule_snippets['snip'])"

And the snippet:

schedule_snippets:
  snip:
  - { start: "12:00", end: "14:00" }
  - { start: "16:00", end: "18:00" }

Hey, you’re right about the single space! Will fix it tomorrow.

Hello!
I just can not manage it.
I installed AppDaemon in HomeAssistant as normal. Then I copied the file hass_apps_loader.py with the following content into the “app” directory:

# This is just a stub which makes the app classes available for AppDaemon.

from hass_apps.loader import *

My appdaemon.yml looks like this:

secrets: /config/secrets.yaml
appdaemon:
  latitude: <geheim>
  longitude: <geheim>
  elevation: 2
  time_zone: Europe/Amsterdam
  plugins:
    HASS:
      type: hass
      ha_url: https://geheim.de
      token: 
http:
  url: http://127.0.0.1:5050
admin:
api:
hadashboard:

I have not yet created a schedy_heating.yaml file because the following error message appears already.

WARNING AppDaemon: No app description found for: /config/appdaemon/apps/hass_apps_loader.py - ignoring

What am I doing wrong?

Did you actually install hass-apps though?
You need to add it to the AppDaemon packages list.
Mine looks like this:

init_commands: []
python_packages:
  - https://github.com/efficiosoft/hass-apps/archive/master.zip
system_packages: []

Thanks, I think it was due to the appdeamon.yaml. The field type: ha_url and token was empty for me. Now it’s working! Thanks very much! :slight_smile:

Hi, Hope someone can help. Been using Schedy reliably for the past 12 months but wanted to reconfigure slightly to tidy things up. Is there any way I could combine the days_off and the school_days_off schedule snippet using an ‘or’?

non-working example,

"Next() if house_mode() != 'Away' and state('sensor.brighthr_leave') == 'on' or house_mode() != 'Away' and state('sensor.school_leave') == 'on' and girls() == 'on' else Break()"

Current working full schedy.yaml

schedy_heating:
  module: hass_apps_loader
  class: SchedyApp
  expressions_from_events: true

  actor_type: thermostat
  
  watched_entities:
  - input_select.home
  - input_boolean.family
  - input_select.heating_preset
  - input_number.temp_home
  - input_boolean.girls
  - input_select.heating_preset_girls
  - input_number.temp_girls
  - sensor.brighthr_leave
  - sensor.school_leave
  
  expression_environment: |
    def house_mode():
      return state("input_select.home")
      
    def family():
      return state("input_boolean.family")

    def climate():
      return state("input_select.heating_preset")
      
    def girls():
      return state("input_boolean.girls")
      
    def climate_girls():
      return state("input_select.heating_preset_girls")
  
  schedule_snippets:
    away:
    - x: "Next() if house_mode() == 'Away' else Break()"
    - { v: 12, start: "06:30", end: "07:30", months: "1-3,10-12" }
    - { v: 12, start: "19:30", end: "20:30", months: "1-3,10-12" }
    boost:
    - x: "Next() if climate() == 'Boost' else Break()"
    - { v: 18.5, start: "07:45", end: "17:00" }
    - { start: "17:00", end: "23:15" }
    days_off:
    - x: "Next() if house_mode() != 'Away' and state('sensor.brighthr_leave') == 'on' else Break()"
    - { x: Add(-2) if family() == 'off' else Next(), months: "3,10,11" }
    - { v: 16.5, start: "01:00", end: "06:30", months: "1,2,12" }
    - { start: "06:30", end: "08:30", months: "1-3,10-12" }
    - { start: "16:00", end: "22:00", months: "1-3,10-12" }
    school_days_off:
    - x: "Next() if house_mode() != 'Away' and state('sensor.school_leave') == 'on' and girls() == 'on' else Break()"
    - { x: Add(-2) if family() == 'off' else Next(), months: "3,10,11" }
    - { v: 16.5, start: "01:00", end: "06:30", months: "1,2,12" }
    - { start: "06:30", end: "08:30", months: "1-3,10-12" }
    - { start: "16:00", end: "22:00", months: "1-3,10-12" }
    work_days:
    - x: "Next() if house_mode() != 'Away' and state('sensor.brighthr_leave') == 'off' else Break()"
    - { x: Add(-2) if family() == 'off' else Next(), months: "3,10,11" }
    - { v: 16.5, start: "01:00", end: "06:30", months: "1,2,12" }
    - { start: "06:30", end: "07:45", months: "1-3,10-12" }
    - { start: "17:30", end: "22:00", months: "1-3,10-12" }
    girls:
    - x: "Next() if girls() == 'on' else Break()"
    - { start: "06:30", end: "07:45", months: "1,2,12" }
    - { start: "17:00", end: "22:00", months: "1,2,12" }
  
  schedule_append:
  - v: "OFF"
  
  rooms:
  
    living:
      rescheduling_delay: 30
      actors:
        climate.heating:
      schedule:
      - x: "state('input_number.temp_home')"
        rules:
        - weekdays: 1-7
          rules:
          - rules:
            - x: "IncludeSchedule(schedule_snippets['boost'])"
          - rules:
            - x: "IncludeSchedule(schedule_snippets['away'])"
          - rules:
            - x: "IncludeSchedule(schedule_snippets['days_off'])"
          - rules:
            - x: "IncludeSchedule(schedule_snippets['school_days_off'])"
          - rules:
            - x: "IncludeSchedule(schedule_snippets['work_days'])"
      
    girls:
      rescheduling_delay: 15
      actors:
        climate.heating_girls:
      schedule:
      - x: "state('input_number.temp_girls')"
        rules:
        - weekdays: 1-7
          rules:
          - rules:
            - x: "IncludeSchedule(schedule_snippets['girls'])"

thanks for any help given.

Hi all,

I wanted to do a light change at my config removing time rule:

    bagnoprincipale:
      actors:
        climate.002018a99d2442:
      watched_entities:
      - binary_sensor.001558a99d4e50_state
      schedule:
      - v: 20
        rules:
        - weekdays: 1-5
          rules:
          - rules:
            - x: "Next() if heating_mode() == 'Acceso' else Break()"
            - { start: "05:30", end: "23:30" }
        - weekdays: 6-7
          rules:
          - rules:
            - x: "Next() if heating_mode() == 'Acceso' else Break()"
    #        - { start: "07:00", end: "23:30" }
      - v: 30
        months: 5-9

But if I do this the valve goes to off and doesn’t turn on anymore. Any hint?

Hello,

I’m having an issue with Schedy (I think).

I have a basic setup where in the morning I want a room to be 22° and in the evening it should be 21°. But it seems the temperature isn’t getting changed.
I am able to reproduce this and this is what I get in the logging:

2021-12-09 08:22:36.719000 INFO schedy_heating: --> [R:bureau] [A:climate.f1_bureau_valve_heater] Received value of 21.0��.
2021-12-09 08:22:38.650882 INFO schedy_heating: <-- [R:bureau] Value set to 20.0��.  [scheduled]
2021-12-09 08:22:38.899680 INFO schedy_heating: --> [R:bureau] [A:climate.f1_bureau_valve_heater] Received value of OFF.

2021-12-09 08:22:46.293561 INFO schedy_heating: --> [R:bureau] [A:climate.f1_bureau_valve_heater] Received value of 21.0��.
2021-12-09 08:23:09.015946 WARNING schedy_heating: !!! [R:bureau] [A:climate.f1_bureau_valve_heater] Re-sending value due to missing confirmation.
2021-12-09 08:23:16.609491 INFO schedy_heating: --> [R:bureau] [A:climate.f1_bureau_valve_heater] Received value of OFF.
2021-12-09 08:23:22.773229 INFO schedy_heating: --> [R:bureau] [A:climate.f1_bureau_valve_heater] Received value of 21.0��.
2021-12-09 08:23:47.023269 WARNING schedy_heating: !!! [R:bureau] [A:climate.f1_bureau_valve_heater] Re-sending value due to missing confirmation.
2021-12-09 08:23:48.687087 INFO schedy_heating: --> [R:bureau] [A:climate.f1_bureau_valve_heater] Received value of OFF.
2021-12-09 08:23:55.040361 INFO schedy_heating: --> [R:bureau] [A:climate.f1_bureau_valve_heater] Received value of 21.0��.
2021-12-09 08:24:19.048870 WARNING schedy_heating: !!! [R:bureau] [A:climate.f1_bureau_valve_heater] Re-sending value due to missing confirmation.
2021-12-09 08:24:20.715912 INFO schedy_heating: --> [R:bureau] [A:climate.f1_bureau_valve_heater] Received value of OFF.
2021-12-09 08:24:27.083429 INFO schedy_heating: --> [R:bureau] [A:climate.f1_bureau_valve_heater] Received value of 21.0��.
2021-12-09 08:24:48.120940 INFO schedy_heating: --> [R:bureau] [A:climate.f1_bureau_valve_heater] Received value of 20.0��.

If I then manually change the value to 20.0, it gets picked up and the retries stop.
It seems to me that the temperature is set too fast while the thermostat is still in OFF mode?

While retrying I constantly see the thermostat card change between off, heat, the wanted temperature and then again the previous temperature.
In the history of the thermostat is says “Turned off by Supervisor”, followed by “Changed to Heat” for every Heaty retry.

If I manually go to the thermostat card and turn on the heater, then change the temperature it gets pushed correctly to the thermostat.

The same happens when I manually override and Schedy tries to re-apply the schedule (here after one minute to simulate)

2021-12-09 08:36:46.482837 INFO schedy_heating: --> [R:bureau] [A:climate.f1_bureau_valve_heater] Received value of 19.5��.
2021-12-09 08:36:46.499857 INFO schedy_heating: --- [R:bureau] Re-applying the schedule not before 08:37:46 (in 0:01:00).
2021-12-09 08:37:47.788518 INFO schedy_heating: <-- [R:bureau] Value set to 20.0��.  [scheduled]
2021-12-09 08:37:47.891875 INFO schedy_heating: --> [R:bureau] [A:climate.f1_bureau_valve_heater] Received value of OFF.
2021-12-09 08:37:54.151336 INFO schedy_heating: --> [R:bureau] [A:climate.f1_bureau_valve_heater] Received value of 19.5��.
2021-12-09 08:38:18.033055 WARNING schedy_heating: !!! [R:bureau] [A:climate.f1_bureau_valve_heater] Re-sending value due to missing confirmation.
2021-12-09 08:38:19.697175 INFO schedy_heating: --> [R:bureau] [A:climate.f1_bureau_valve_heater] Received value of OFF.
2021-12-09 08:38:26.046954 INFO schedy_heating: --> [R:bureau] [A:climate.f1_bureau_valve_heater] Received value of 19.5��.

Anything I can try to pinpoint the issue?

thanks,
Stijn

@roschi can you confirm whether Schedy will be affected by any of these breaking changes:

Thanks.

1 Like

@mobile.andrew.jones I can at least confirm updating worked without any problems. I run Appdaemon4 0.4.2 since it was released without issues in 2 installation,

1 Like

Thought it was worth checking as I rely on it for the heating system, and since they specifically mention changes in how the state listeners work, I would assume Schedy uses entity state listeners to re-evaluate the schedule.

If you have a backup you can easily just rol back the app daemon version in case a problem occurs :wink:
I did not get any strange messages in my log.

Hello,

i really thank you for that awesom tool. i just got into HA and schedy and i got some questions.
I set up my rooms and heating times, so far so good.

Q1:

i.e.:

  schedule_snippets:
    grundwaerme_preset1:
      - v: 19
        rules:
          - weekdays: 1-7
            rules:
              - { start: "07:00", end: "07:59" }

i wanted to set something like a heaing season for all rooms and all “-v” and it seems to work like this:

  schedule_snippets:
    grundwaerme_preset1: #Raeume: Bad, WC, Arbeitszimmer, Kueche
      - v: 19
        start_date: { year: 2021, month: 10, day: 1 }
        end_date: { year: 2022, month: 4, day: 1 }
        weekdays: 1-7
        start: "07:00"
        end: "07:59"

but i would need to add the start_date and end_date for each one. is there a way to make is not redundant? also it would be nice to get start and end date from HA so i could change the start and end of heaing season there.

Q2:

i got external temp sensors which i would like to use with my heaters.
so i.e. the thermostate which has got a temp sensor in it says its 20C, but the external sensor says its 18C, and the termperature is set to be 21C, i would like to add those 2C which are diffrent to the set temperature like an offset, so the set temperature would change to 23C

is that possible?

Hi,

I have a problem with Schedy not evaluating my dynamic schedule on a regular basis, only when watched enties are changed. Any idea why, and how to make it work?

schedy_heating:  # This is our app instance name.
  module: hass_apps_loader
  class: SchedyApp

  expression_environment: |
    def time_between(start, end):
        current = time.hour
        if start >= end:
            return current >= start or current < end
        return current >= start and current < end

  actor_type: thermostat
  
  watched_entities:
### Gjeldende
  - switch.bortemodus_switch
  - sensor.pricelevel
  - input_number.st_feriemodus
  - input_number.st_rom_ikke_i_bruk
  - input_number.tk_boost_varme
  - input_number.tk_sp_h
  - input_number.tk_sp_vh

  schedule_snippets:
    modifikator:
    - x: "Add(state('input_number.tk_sp_h')) if state('sensor.pricelevel') == 'EXPENSIVE' else Next()"
    - x: "Add(state('input_number.tk_sp_vh')) if state('sensor.pricelevel') == 'VERY_EXPENSIVE' else Next()"

  rooms:

## Kontor ##
    Kontor:
        rescheduling_delay: 120
        actors:
            climate.socket_kontor:

        watched_entities:
        - input_boolean.rib_r301
        - input_number.tk_bm_r301
        - input_number.tk_sm_r301
        - input_number.tik_fv_r301
        - input_number.st_m_r301
        - input_number.st_d_r301
        - input_number.st_k_r301
        - input_number.st_n_r301

        - input_number.pt_mt_m_r301
        - input_number.pt_mt_d_r301
        - input_number.pt_mt_k_r301
        - input_number.pt_mt_n_r301
        - input_number.pt_f_m_r301
        - input_number.pt_f_d_r301
        - input_number.pt_f_k_r301
        - input_number.pt_f_n_r301
        - input_number.pt_l_m_r301
        - input_number.pt_l_d_r301
        - input_number.pt_l_k_r301
        - input_number.pt_l_n_r301
        - input_number.pt_s_m_r301
        - input_number.pt_s_d_r301
        - input_number.pt_s_k_r301
        - input_number.pt_s_n_r301

        schedule:
        - v: 10
          rules:
            - weekdays: 1-4
              rules:
                - x: "Break() and state('input_number.st_rom_ikke_i_bruk') if is_on('input_boolean.rib_r301') else Next()"
                - x: "IncludeSchedule(schedule_snippets['modifikator'])"
                - x: "Add(state('input_number.tk_bm_r301')) if is_on ('switch.bortemodus_switch') else Next()"
                - x: "state('input_number.st_m_r301') if time_between(float(state('input_number.pt_mt_m_r301')), float(state('input_number.pt_mt_d_r301'))) else Next()"
                - x: "state('input_number.st_d_r301') if time_between(float(state('input_number.pt_mt_d_r301')), float(state('input_number.pt_mt_k_r301'))) else Next()"
                - x: "state('input_number.st_k_r301') if time_between(float(state('input_number.pt_mt_k_r301')), float(state('input_number.pt_mt_n_r301'))) else Next()"
                - x: "state('input_number.st_n_r301') if time_between(float(state('input_number.pt_mt_n_r301')), float(state('input_number.pt_mt_m_r301'))) else Next()"
            - weekdays: 5
              rules:
                - x: "Break() and state('input_number.st_rom_ikke_i_bruk') if is_on('input_boolean.rib_r301') else Next()"
                ...and so on...

Best Regards
Jan-Tore

Hi @TriStone

I love what you’ve done and I have modified your code a little bit to fit my setup.
One problem I have run into is that the dynamic times are not beeing evalutated, so the temperature stays the same until someting triggers an evalutation (may take many hours).
Have you seen this problem? And do you have a solution?

See more details in my post: Heaty will die, Schedy be born! - #1268 by Autoper

Best Regards
Jan-Tore