Heaty will die, Schedy be born!

But even when you accidentally do, you can now recover without restarting anything just by closing, doing a manual change and then reopening the window.

Hi Robert,

At first: thanks for the great work and even more for sharing it with us!!!

I’m currently tranfering my heating schedule from heaty to schedy and it worked fine so far but now I’d like to add the window sensors and… well… it’s stange.

I constumized my sensor within my customize.yaml like this:

binary_sensor.wohnzimmerfenster_50_0:
  window_room: wohnzimmer

my cut down apps.yaml (just removed the other rooms) looks like this:

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

  actor_type: thermostat
  
  watched_entities:
  - input_select.heating_mode
  
  schedule_prepend:
  - x: "Mark(OFF, Mark.OVERLAY) if not is_empty(filter_entities('binary_sensor', State='on', window_room=room_name))"
  
  schedule_append:  
  - v: 19
    rules:
      - x: "Skip() if state('input_select.heating_mode') != 'Urlaub (abwesend)' else Break()"
      - { start: "00:00", end: "23:59" }
  - v: 17

  rooms:
    
    # ------------------- WOHN - ZIMMER -------------------
    wohnzimmer:
      rescheduling_delay: 60
      actors:
        climate.wohnzimmer:
      watched_entities:
      - binary_sensor.wohnzimmerfenster_50_0
      schedule:
      - v: 23
        rules:
        - weekdays: 1-5
          rules:
            - rules:
              - x: "Skip() if state('input_select.heating_mode') == 'Normal' else Break()"
              - { start: "15:00", end: "23:00" }
            - rules:
              - x: "Skip() if state('input_select.heating_mode') == 'Dienstfrei' else Break()"
              - { start: "10:00", end: "23:00" }
            - rules:
              - x: "Skip() if state('input_select.heating_mode') == 'Home Office Marco' else Break()"
              - { start: "07:30", end: "22:30" }
            - rules:
              - x: "Skip() if state('input_select.heating_mode') == 'Urlaub (anwesend)' else Break()"
              - { start: "08:00", end: "23:30" }
        - weekdays: 6-7
          rules:          
            - rules:
              - x: "Skip() if state('input_select.heating_mode') != 'Urlaub (abwesend)' else Break()"
              - { start: "08:00", end: "23:30" }

The debug output of AppDeamon provides this:

2019-09-26 23:22:52.953324 INFO AppDaemon: App 'schedy_heating' changed
2019-09-26 23:22:52.960113 INFO AppDaemon: Terminating schedy_heating
2019-09-26 23:22:52.961704 INFO AppDaemon: Initializing app schedy_heating using class SchedyApp from module hass_apps_loader
2019-09-26 23:22:52.966898 INFO schedy_heating: *** Welcome to schedy 0.5.0, running on AppDaemon 3.0.5.
2019-09-26 23:22:52.971547 INFO schedy_heating: *** 
2019-09-26 23:22:52.976212 INFO schedy_heating: *** This is an app from the hass-apps package.
2019-09-26 23:22:52.980903 INFO schedy_heating: ***   DOCS: xxx
2019-09-26 23:22:52.985551 INFO schedy_heating: *** 
2019-09-26 23:22:52.990193 INFO schedy_heating: *** You like this app, want to honor the effort put into
2019-09-26 23:22:52.994815 INFO schedy_heating: *** it, ensure continuous development and support?
2019-09-26 23:22:52.999468 INFO schedy_heating: *** Then please consider making a donation.
2019-09-26 23:22:53.007000 INFO schedy_heating: ***   DONATE: xxx
2019-09-26 23:22:53.011101 INFO schedy_heating: *** Thank you very much and enjoy schedy!
2019-09-26 23:22:53.015138 INFO schedy_heating: *** 
2019-09-26 23:22:53.019229 INFO schedy_heating: --- Validating the app's configuration.
2019-09-26 23:22:53.126942 ERROR schedy_heating: !!! Configuration error: Couldn't compile expression: "Mark(OFF, Mark.OVERLAY) if not is_empty(filter_entities('binary_sensor', State='on', window_room=room_name))" @ data['schedule_prepend'][0]. Got {'x': "Mark(OFF, Mark.OVERLAY) if not is_empty(filter_entities('binary_sensor', State='on', window_room=room_name))"}
2019-09-26 23:22:53.130869 ERROR schedy_heating: !!! Not initializing this app.

If i remove the two “schedule_prepend”-lines everything works like it should. So is there a syntax error in the expression?

I can confirm, that the costumization of the binary sensor was sucessfull. I can see the new attibute “window_room” and the value “wohnzimmer” in the overview of binary_sensor.wohnzimmerfenster_50_0.

I’m running out of ideas here. Every hint is appreciated. If you need more information or log file snippets, pls let me know.

Best Regards,
Marco

Hi @JustSomeRandomDIYGuy

Thanks for the appreciation.

Mark(OFF, Mark.OVERLAY) if not is_empty(filter_entities('binary_sensor', State='on', window_room=room_name))

That expression is faulty in multiple ways, syntax-wise and capitalization-wise… Could you please link the docs page you got this from?

Good Morning,

Thanks for the rapid reaction.

I copied those lines from the schedy-documentation: https://hass-apps.readthedocs.io/en/stable/apps/schedy/tutorial.html#adding-window-sensors

The same lines are also included in the “final configuration” section close to the end of this tutorial.

Regards,
Marco

Please have a close look at it again, that line is

  1. longer than the part you use in your schedule and
  2. you capitalized state, which is wrong…

So you clearly haven’t copied it :slight_smile:

EDIT: And, just in case you didn’t notice it, there was a new release this morning, so the docs you linked only work after you upgraded.

Hi Robert,

great. That does the trick. Just two additional words and it’s up an running.

And considerting the copying: Is it possible that you modified that line of the docs quite recently? Even when I opened that docs angain after your last post, I got a version displayed by my browser in which this “else Next()” add-on was still missing. Only a enforced reload of the web page gave me the correct version.

So probably my browser cache was the devil here.

Anyway, thanks for the supoort!!! Great piece of software.

Best Regards from a well-tempered office :-),
Marco

Ah, right, there was commit e88576c0 which fixed that line in the tutorial, but in the window sensor docs it always was correct.

Thanks for the continous development.

I’ve upgraded HA to 0.99.3 and Schedy to actual version and all seems to work as expected :+1:

1 Like

Is it possible to link two radiator thermostats? Both thermostats belong to the same room. I would like to mirror settings made by HA, Schedy or to the thermostat directly.

Is it possible to link two radiator thermostats? Both thermostats belong to the same room. I would like to mirror settings made by HA, Schedy or to the thermostat directly.

Well, that’s the purpose of a room in Schedy. :slight_smile:
Unless you explicitly opt out by disabling replicate_changes, all changes are replicated among actors in a room.

EDIT: BTW, this is one of the top features listed on Schedy’s docs’ entry page.

2 Likes

Hi there,
I’m finally trying to migrate from Heaty to Schedy. The new features like watch entities will allow me to streamline a lot of workarounds I built with switches and automations within Home assistant directly int Schedy but im terrible at Python and the expressions give me a hard time. Can anyone help me fixing the following expression?
My target is to define the start and end of my schedules basen on whether or not “today” and “tomorrow” are working days using workingday binary sensors. I used this for Heaty as well because this gives an added value over weekdays by considering bank holidays as well.

In heaty my code was a mess (but working) now I want to simplify it but I can’t get it to work at all.

When migrating it line by line from heaty and adding the “x:” to it the “start” and “end” strigs seem to cause a problem:

- x: "state('input_number.heat_livingroom') if is_on('binary_sensor.workday_today') and is_on('binary_sensor.workday_tomorrow') else Next(), start: '06:00', end: '22:00'"

I also tried taking it apart without success:

        - x: "state('input_number.heat_livingroom')"
          rules:
          - x: "Next() if is_on('binary_sensor.workday_today') and is_on('binary_sensor.workday_tomorrow') else Break()"
          - { start: "06:00", end: "22:00" }
          rules:
          - x: "Next() if is_on('binary_sensor.workday_today') and is_off('binary_sensor.workday_tomorrow') else Break()"
          - { start: "06:00", end: "00:00" }
          rules:
          - x: "Next() if is_off('binary_sensor.workday_today') and is_on('binary_sensor.workday_tomorrow') else Break()"
          - { start: "08:00", end: "22:00" }    
          rules:
          - x: "Next() if is_off('binary_sensor.workday_today') and is_off('binary_sensor.workday_tomorrow') else Break()"
          - { start: "08:00", end: "00:00" }    

Is there a simpler way to implement the desired behavior?

Thanks

Hi @Nigggo

It’s important for you to understand what the YAML parser does with your input to be able to write correct YAML.

- x: "state('input_number.heat_livingroom') if is_on('binary_sensor.workday_today') and is_on('binary_sensor.workday_tomorrow') else Next(), start: '06:00', end: '22:00'"

The YAML parser renders this list item into a dictionary with a single key x, mapped to the string value state('input_number.heat_livingroom') if is_on('binary_sensor.workday_today') and is_on('binary_sensor.workday_tomorrow') else Next(), start: '06:00', end: '22:00'. So, basically, you’re telling Schedy that all of this string is the expression, which isn’t what you want.

Instead, you want to express a dictionary with three keys: the expression, the start and the end time.

Your second code block is no valid YAML altogether, for instance because you specify keys (rules) twice in a single dictionary. If you want to go that second route, and I’d clearly prefer that because of less repitition and clearer structure, you’ll need two levels of nesting, one for the target temperature and one for filtering out the working day combinations.

Best regards
Robert

Hi Robert,

thank you a lot for that explanation. Since I don’t have any coding bacground it has been trial and error for me all along so your insight of the logic behind it helps a lot :slight_smile:

Can you help me out how this proper nesting can be done? My interpretation of the rules: block was that this is how I can nest the different expressions seperately.

thank you a lot for that explanation. Since I don’t have any coding bacground it has been trial and error for me all along so your insight of the logic behind it helps a lot :slight_smile:

No problem, actually, understanding YAML syntax is the key point here, for which there are lots of references out there.

Can you help me out how this proper nesting can be done? My interpretation of the rules: block was that this is how I can nest the different expressions seperately.

You need two levels of sub-schedules. The outmost rule sets the target temperature and should have a sub-schedule (rules attribute containing a list, not dictionary) of four expression-less rules, each of which again has a sub-schedule with two rules.

Content-wise, the thing you posted is almost correct already, just the structure is not

Thanks again, I wouldn’t have come up with that by myself.

If others need inspiration, this seems to work even though there must be a cleaner way:

        - x: "state('input_number.heat_livingroom')"
          rules:
            - 
              rules:
              - x: "Next() if is_on('binary_sensor.workday_today') and is_on('binary_sensor.workday_tomorrow') else Break()"
              - start: "6:00"
              - end: "22:00"
            - 
              rules:
              - x: "Next() if is_off('binary_sensor.workday_today') and is_on('binary_sensor.workday_tomorrow') else Break()"
              - start: "8:00"
              - end: "22:00"
            - 
              rules:
              - x: "Next() if is_on('binary_sensor.workday_today') and is_off('binary_sensor.workday_tomorrow') else Break()"
              - start: "6:00"
              - end: "00:00"
            - 
              rules:
              - x: "Next() if is_off('binary_sensor.workday_today') and is_off('binary_sensor.workday_tomorrow') else Break()"
              - start: "8:00"
              - end: "00:00"
1 Like

If others need inspiration, this seems to work even though there must be a cleaner way:

No, that doesn’t work as expected. You can’t simply put a dash infront of everything :slight_smile:. That creates rules you don’t want, one that goes from midnight to 6:00, one from 22:00 to midnight and so on…

EDIT: You already had the correct syntax for single-line rules as described in the docs before:

- { start: "06:00", end: "22:00" }

EDIT 2: Ah, and if you put those - infront of rules directly rather than on an extra line, it get’s even cleaner.

1 Like

I was so proud to solve it and you kill it :slight_smile:

Thanks for your patience, I thought the “end” and “start” keys could be in seperate items of the list as well without a problem.

I hope now it’s finally correct:

      schedule:
        - x: "'off' if is_on('input_boolean.heat_off_unten') else Next()"
        - x: "state('input_number.heat_livingroom')"
          rules:
            - rules:
              - x: "Next() if is_on('binary_sensor.workday_today') and is_on('binary_sensor.workday_tomorrow') else Break()"
              - { start: "6:00", end: "22:00"}
            - rules:
              - x: "Next() if is_off('binary_sensor.workday_today') and is_on('binary_sensor.workday_tomorrow') else Break()"
              - { start: "8:00", end: "22:00"}
            - rules:
              - x: "Next() if is_on('binary_sensor.workday_today') and is_off('binary_sensor.workday_tomorrow') else Break()"
              - { start: "6:00", end: "00:00"}
            - rules:
              - x: "Next() if is_off('binary_sensor.workday_today') and is_off('binary_sensor.workday_tomorrow') else Break()"
              - { start: "8:00", end: "00:00"}```

Hehe, looks …almost… great :stuck_out_tongue:

It’s the special object OFF instead of the string 'off' for thermostats. You can verify that rule evaluation fails right now when you turn that heating_off_downstairs switch on. Good work apart from that!

EDIT: I was partially wrong, it actually will work this way because there is an automatic conversion from 'off' to OFF.

Hi all,

it’s winter time (autumn actually) and I buyed some Homematic IP valve to automate my heating.

So I started studing Schedy but I see error in logs.

Below my config:

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

  actor_type: thermostat

  expression_environment: |
    def heating_mode():
        return state("input_select.heating_mode")

  schedule_snippets:
    bagni:
    - v: 22
      rules:
      - x: "Next() if heating_mode() == 'In Casa' else Break()"
      - { start: "05:30", end: "22:00", weekdays: "1-5" }
      rules:
      - x: "Next() if heating_mode() == 'In Casa' else Break()"
      - { start: "07:30", end: "22:00", weekdays: "6-7" }

  watched_entities:
  - input_select.heating_mode

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


#modalità base
  schedule_append:
  - v: "OFF"

#modalità estiva
  - { v: 30, months: "5-9" }


  rooms:

    bagnoprincipale: #kids1:
      #allow_manual_changes: false
      actors:
        climate.002018a99d2442:
      #watched_entities:
      #- binary_sensor.kids1_window_1
      schedule:
      - x: "IncludeSchedule(schedule_snippets['bagni'])"

    bagnosecondario: #kids2:
      #allow_manual_changes: false
      actors:
        climate.002018a99ebe4e:
      #watched_entities:
      #- binary_sensor.kids2_window_1
      schedule:
      - x: "IncludeSchedule(schedule_snippets['bagni'])"

    soggiorno:
      rescheduling_delay: 120
      actors:
        climate.002018a99d1262:
      #watched_entities:
      #- binary_sensor.001558a99d47fc_state
      schedule:
      - v: 21
        rules:
        - x: "Next() if heating_mode() == 'In Casa' else Break()"
        - { start: "05:30", end: "09:00", start: "15:30", end: "22:00", weekdays: "1-5" }
      rules:
        - x: "Next() if heating_mode() == 'In Casa' else Break()"
        - { start: "07:30", end: "22:00", weekdays: "6-7" }

Some explenations:

What i want to achieve is set to zero if status is not home (“Fuori Casa” ) and to different temperature if home (“In Casa”).

Moreover during spring and summer i want to open valves completely for system maintenance of the building (water changing and so on).

This is the error I see in log:

> 2019-10-18 10:26:25.217340 ERROR schedy_heating: !!! Configuration error: extra keys not allowed @ data['rooms']['soggiorno']['rules']. Got [{'x': "Next() if heating_mode() == 'In Casa' else Break()"}, {'start': '07:30', 'end': '22:00', 'weekdays': '6-7'}]
> 2019-10-18 10:26:25.217826 ERROR schedy_heating: !!! Not initializing this app.

Can someone please help me?

Thank you in advance

Hi,

There are multiple issues here. These are no valid sub-schedule rules. Additionally, you got the indentation wrong and thus have an invalid config structure, which is what the error message is telling you.

After all, I see lots of similarities to the problem @Nigggo had some days ago, so please see the explanations I gave him back then and his solution.