Heaty will die, Schedy be born!

Every attribute you configure for an actor will trigger a service call when a value is set, that’s expected behavior.

The problem is that your light entity does not have an attribute brightness_pct which should reflect the value set in the second attribute slot. Maybe that attribute is just named differently than the parameter to be sent when turning on? You could use the HA developer tools to inspect the available attributes and eventually change the attribute: brightness_pct in Schedy’s config to the correct attribute name.

Without this relation, Schedy isn’t able to detect that the value has been set successfully and hence continue re-sending it. However, the warning message with send_retries: 0 is quite confusing, I’ll rework that code eventually to produce better log messages.

You are correct, the brightness_pct value worked but it did not get set on the lights after the change. Changing to brightness instead worked better and now it seems to understand that the value has changed.

On another note, would it be possible to add like a “variables:” section to the config where you could declare “constants” which would then work wherever you put it in the config?

Would be neat in my case to define some standard values like:

variables:
  BRIGHTNESS_50: 127

schedule:
  - v: ['on', BRIGHTNESS_50]

Once again, thanks for this awesome “script”!

On another note, would it be possible to add like a “variables:” section to the config where you could declare “constants” which would then work wherever you put it in the config?

Have a look at the expression_environment setting.

EDIT: You could even declare a function that converts arbitrary percentages and call that from your schedule.

EDIT 2:
Something like this:

expression_environment: |
  def pct2byte(pct):
      """Converts a percentage to an integer in range 0..255."""
      # Use int instead of round to get the floor function, i.e. to map 50% to 127 instead of 128
      return round(max(0, min(255, pct)) * 255 / 100)

Thanks, worked wonders, did this:

expression_environment: |
    def pct2byte(pct):
        """Converts a percentage to an integer in range 0..254."""
        return int(round(max(0, min(254, pct)) * 255 / 100))

schedule_prepend:
    - x: |
        def convert(r):
            if isinstance(r, (tuple)):
                return [r[0], pct2byte(r[1])]
            return r
        result = Postprocess(convert)

Only thing I can’t get working now is when I mix switches with lights:

actors:
  light.livingroom_wall_lightstrip_right:
  switch.zwave_002_switch:
    template: switch

Getting this in the log:

2019-10-31 20:49:24.073730 INFO schedy_lights: --> [R:Vardagsrum] [A:switch.zwave_002_switch] Received value of 'off'.
2019-10-31 20:49:24.749041 WARNING schedy_lights: !!! [R:Vardagsrum] [A:switch.zwave_002_switch] VALUe ['on', 166] should be shortened to ('on',), doing it for you now.

And this is the actor template:

switch:
  attributes:
    - attribute: state
      values:
        "on":
          service: switch.turn_on
        "off":
          service: switch.turn_off
    - attribute: null
      values:
        "_other_":
          service: switch.turn_on
          value_parameter: null

Had to add the null value, otherwise it would throw an error because of the “tuple” I use for on values. I solved this in my garage by putting a postprocessor in the front:
- x: "Postprocess(lambda result: (result[0] if isinstance(result, (tuple)) else result))"
But, in the garage I only have a switch so that works for that room.

Well, you should probably create two rooms, one for the lights and one for the switches and eventually use the same schedule snippet for both. Then you can prepend a postprocessor that truncates the result depending on the value of the room_name variable and remove the null attribute completely.

BTW, I’m currently reworking the generic actor completely but don’t have docs yet, if you’d like to try it out, please let me know.

I have a schedy related request with multi-entity dependencies in order for it to work properly. See my post here:

Looking forward for your ideas.

I’m using Schedy to control a number of Danfoss ZWave radiator thermostats. configuration.yaml has the following snippet:

climate:
  - platform: zwave

The thermostats are discovered and added OK and I can control them manually from HA. However, Schedy is complaining that they are misconfigured:

2019-11-08 09:20:32.494774 WARNING schedy_heating: !!! [R:bedroom_1] [A:climate.bedroom_1_radiator_thermostat] The value None for attribute 'current_temperature' is no valid temperature value. Please check your config!
2019-11-08 09:20:32.501515 WARNING schedy_heating: !!! [R:bedroom_1] [A:climate.bedroom_1_radiator_thermostat] Attributes for thermostat contain no 'hvac_modes', Consider disabling HVAC mode support.
2019-11-08 09:20:32.516496 ERROR schedy_heating: !!! [R:bedroom_1] [A:climate.bedroom_1_radiator_thermostat] Unknown HVAC mode 'unknown', ignoring thermostat.
2019-11-08 09:20:32.808413 INFO schedy_heating: <-- [R:bedroom_1] Value set to 15.0��.  [scheduled]

I assume I need to add something into configuration.yaml, but what?

Do you have HA version 0.96+ ?
There was a big change in modes handling, introducing the hvac_modes.

If not, upgrade.

If so then it looks like issue of the component. But that’s strange as it is standard Z-Wave component.

I have Eurotronic Z-Wave, same category. And the details in states look like this:

So you can compare.

@Guff666 I know that the Danfos thermostats don’t report the current temperature as measured by their internal sensor, which causes the warning about current_temperature being None. You can safely ignore that warning, it just means that temp_delta statistics won’t work.

Regarding the HVAC modes, see the answer of @TriStone

1 Like

Is it possible to use the if-statement without any other statement at the beginning?
I would like to do the following:

      schedule:
      - v: 22
        rules:
          - rules:
            - x: "if state('media_player.my_tv') == 'playing' else Next()" # just use the parent temperature if tv is on
            - x: "Next() if is_on('binary_sensor.workday_sensor') else Break()"
            - { start: "17:00", end: "22:15" }

I only found this way but then I have to write the temperature twice:

      schedule:
      - x: "22 if state('media_player.my_tv') == 'playing' else Next()"
      - v: 22
        rules:
          - rules:
            - x: "Next() if is_on('binary_sensor.workday_sensor') else Break()"
            - { start: "17:00", end: "22:15" }

You should be able to do this:

schedule:
  - v: 22
    rules:
      - x: "Inherit() if state('media_player.my_tv') == 'playing' else Next()" # just use the parent temperature if tv is on
      - x: "Next() if is_on('binary_sensor.workday_sensor') else Break()"
      - { start: "17:00", end: "22:15" }
1 Like

I have got this configuration:

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

  actor_type: thermostat

  schedule_append: # temp called if no schedule set
    - v: 10
  schedule_prepend:
    - x: "Add(-3) if state('input_boolean.cv_besparing') == 'on' else Next()"

  watched_entities:
  - input_boolean.cv_besparing

  rooms:
  
    woonkamer:
      actors:
        climate.woonkamer:
      schedule:
        - v: 20
          weekdays: 1-7
          rules:
            - { start: "07:00", end: "22:00" }

    hal:
      actors:
        climate.hal:
      schedule:
        - v: 18
          weekdays: 1-7
          rules:
            - { start: "07:30", end: "21:00" }

    toilet:
      actors:
        climate.toilet:
      schedule:
        - v: 18
          weekdays: 1-7
          rules:
            - { start: "07:30", end: "21:00" }

No errors in the log file about this config but nothing happent…

No errors in the log file about this config but nothing happent…

@Cinamon Set debug: true in the config and upload the resulting log e.g. to GitHub gists.

hi @roschi I am from heaty where open window sensor was easier for me to do. I now jumped into shedy and fail to get the open window thiing working

That’s my config:

bedroom_heating:
  module: hass_apps_loader
  class: SchedyApp

  actor_type: thermostat

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

  schedule_snippets:
    bedroom:
    - v: 21
      rules:
      - weekdays: 1-5
        rules:
        - rules:
          - x: "Next() if heating_mode() != 'All Home' else Break()"
          - { start: "06:00", end: "07:00" }
          - { start: "22:00", end: "23:59" }
        - rules:
          - x: "Next() if heating_mode() == 'All Home' else Break()"
          - { start: "07:30", end: "20:00" }
      - weekdays: 6-7
        rules:
        - { start: "22:30", end: "23:59" }

  watched_entities:
  - input_select.heating_mode

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


  schedule_append:
  - v: "OFF"

  rooms:

    bedroom:
      rescheduling_delay: 15
      actors:
        climate.air_conditioner_bedroom:
      watched_entities:
      - binary_sensor.window_bedroom
      schedule:
      - x: "IncludeSchedule(schedule_snippets['bedroom'])"

  statistics:
    # Pick an arbitrary name for the parameter instance.
    bedroom_temp_delta:
      # The type of parameter as found in the actor'S documentation.
      type: temp_delta
      # More parameter-specific settings:
      rooms:
        bedroom:

In logs i get fine:

2019-11-09 19:14:09.044877 INFO AppDaemon: Initializing app bedroom_heating using class SchedyApp from module hass_apps_loader


2019-11-09 19:14:09.047651 INFO bedroom_heating: *** Welcome to schedy 0.6.0, running on AppDaemon 3.0.5.


2019-11-09 19:14:09.049960 INFO bedroom_heating: *** 


2019-11-09 19:14:09.052346 INFO bedroom_heating: *** This is an app from the hass-apps package.


2019-11-09 19:14:09.054561 INFO bedroom_heating: ***   DOCS: https://hass-apps.readthedocs.io/en/stable/


2019-11-09 19:14:09.056712 INFO bedroom_heating: *** 


2019-11-09 19:14:09.058950 INFO bedroom_heating: *** You like this app, want to honor the effort put into


2019-11-09 19:14:09.061346 INFO bedroom_heating: *** it, ensure continuous development and support?


2019-11-09 19:14:09.063621 INFO bedroom_heating: *** Then please consider making a donation.


2019-11-09 19:14:09.065697 INFO bedroom_heating: ***   DONATE: https://hass-apps.readthedocs.io/en/stable/#donations


2019-11-09 19:14:09.067685 INFO bedroom_heating: *** Thank you very much and enjoy schedy!


2019-11-09 19:14:09.069677 INFO bedroom_heating: *** 


2019-11-09 19:14:09.082520 INFO bedroom_heating: --- Actor type is: 'thermostat'


2019-11-09 19:14:09.109025 INFO bedroom_heating: --> [R:bedroom] [A:climate.air_conditioner_bedroom] Received value of 23.0��.


2019-11-09 19:14:09.132147 INFO bedroom_heating: --- [R:bedroom] Re-applying the schedule not before 19:19:32 (in 0:05:23).


2019-11-09 19:14:09.537229 INFO bedroom_heating: *** Initialization done.


2019-11-09 19:15:43.096871 INFO bedroom_heating: --> Attribute 'state' of 'binary_sensor.window_bedroom' changed from 'off' to 'on', reevaluating <Room R:bedroom>.


2019-11-09 19:16:52.532094 INFO bedroom_heating: --> Attribute 'state' of 'input_select.heating_mode' changed from 'Parents Home' to 'All Home', reevaluating <Room R:bedroom>.


2019-11-09 19:17:00.564407 INFO bedroom_heating: --> Attribute 'state' of 'binary_sensor.window_bedroom' changed from 'on' to 'off', reevaluating <Room R:bedroom>.


2019-11-09 19:17:16.332689 INFO bedroom_heating: --> Attribute 'state' of 'binary_sensor.window_bedroom' changed from 'off' to 'on', reevaluating <Room R:bedroom>.


2019-11-09 19:17:49.795295 INFO bedroom_heating: --> Attribute 'state' of 'binary_sensor.window_bedroom' changed from 'on' to 'off', reevaluating <Room R:bedroom>.


2019-11-09 19:19:32.614266 INFO bedroom_heating: <-- [R:bedroom] Value set to OFF.  [scheduled]

So if I open the window, the air conditioner won’t turn off :confused: i use the example in the docs. and was wondering if i miss something?

My customize.yaml:


binary_sensor.window_bedroom:
  window_room: bedroom

After watching the attributes of the binary_sensor.window_bedroom i found out that the attribute window_room was not set even I set this attribute in the customize.yaml. I now added those attribute manually via GUI in homeassistant frontend and it appearsimage

Hmm… But it still does not work:

2019-11-10 11:34:09.400167 INFO bedroom_heating: --> [R:bedroom] [A:climate.air_conditioner_bedroom] Received value of 21.0��.

2019-11-10 11:34:09.407801 INFO bedroom_heating: — [R:bedroom] Re-applying the schedule not before 11:49:09 (in 0:15:00).

2019-11-10 11:34:24.579696 INFO bedroom_heating: --> Attribute ‘state’ of ‘binary_sensor.window_bedroom’ changed from ‘off’ to ‘on’, reevaluating .

2019-11-10 11:35:07.136110 INFO bedroom_heating: --> Attribute ‘state’ of ‘binary_sensor.window_bedroom’ changed from ‘on’ to ‘off’, reevaluating .

Here my config agaon:

https://pastebin.com/hn1ubTB0

I just created a debug log for my issue. I opened a window to turn off the climate component and this is the result:

2019-11-10 15:24:22.003642 INFO bedroom_heating: --- [SP:bedroom_temp_delta] Value for A:climate.air_conditioner_bedroom in R:bedroom is 0.0.
2019-11-10 15:24:22.005475 INFO bedroom_heating: --- [SP:bedroom_temp_delta] Unchanged HA state: attributes={'min': 0.0, 'avg': 0.0, 'max': 0.0}
2019-11-10 15:25:43.929221 INFO bedroom_heating: --> [R:bedroom] [A:climate.air_conditioner_bedroom] Attribute 'state' is 'heat'.
2019-11-10 15:25:43.932994 INFO bedroom_heating: --> [R:bedroom] [A:climate.air_conditioner_bedroom] Attribute 'temperature' is 30.0.
2019-11-10 15:25:43.935268 INFO bedroom_heating: --> [R:bedroom] [A:climate.air_conditioner_bedroom] Attribute 'current_temperature' is 22.8.
2019-11-10 15:25:43.937232 INFO bedroom_heating: --> [R:bedroom] [A:climate.air_conditioner_bedroom] Received value of 30.0��.
2019-11-10 15:25:43.939711 INFO bedroom_heating: --- [R:bedroom] Setting value to 30.0��.  [manual]
2019-11-10 15:25:43.949057 INFO bedroom_heating: --- [R:bedroom] [A:climate.air_conditioner_bedroom] Not sending value 30.0�� redundantly.
2019-11-10 15:25:43.951299 INFO bedroom_heating: --- [R:bedroom] Re-applying the schedule not before 15:40:43 (in 0:15:00).
2019-11-10 15:25:43.953091 INFO bedroom_heating: --- [SP:bedroom_temp_delta] Going to update statistics in 3 seconds.
2019-11-10 15:25:43.971036 INFO bedroom_heating: <-- [R:bedroom] Sending state to HA: state='30.0', attributes={'actor_wanted_values': {'climate.air_conditioner_bedroom': '30.0'}, 'scheduled_value': 'OFF', 'rescheduling_time': 1573396843.0, 'overlay_active': False}
2019-11-10 15:25:46.004839 INFO bedroom_heating: --- [SP:bedroom_temp_delta] Value for A:climate.air_conditioner_bedroom in R:bedroom is 7.199999999999999.
2019-11-10 15:25:46.006213 INFO bedroom_heating: <-- [SP:bedroom_temp_delta] Sending state to HA: attributes={'min': 7.2, 'avg': 7.2, 'max': 7.2}
2019-11-10 15:28:33.852970 INFO bedroom_heating: --> Attribute 'state' of 'binary_sensor.window_bedroom' changed from 'off' to 'on', reevaluating <Room R:bedroom>.
2019-11-10 15:28:33.854094 INFO bedroom_heating: --- [R:bedroom] Doing schedule re-evaluation in 1 second [reset=False]
2019-11-10 15:28:34.038036 INFO bedroom_heating: --- [R:bedroom] Evaluating room's schedule (reset=False, force_resend=False).
2019-11-10 15:28:34.039271 INFO bedroom_heating: --- [R:bedroom] Assuming it to be 2019-11-10 15:28:34.
2019-11-10 15:28:34.040483 INFO bedroom_heating: --- [R:bedroom] ������ [SUB]  <<Schedule 'bedroom'>/1:<Rule with sub <Schedule 'prepend'>>>
2019-11-10 15:28:34.041734 INFO bedroom_heating: --- [R:bedroom]     ������ [ACT]  <<Schedule 'bedroom'>/1/1:<Rule x='Mark(OFF, Mark.OVERLAY) if not is_empty('...>>
2019-11-10 15:28:34.043220 INFO bedroom_heating: --- [R:bedroom] Initializing expression helper: BasicHelper, order = 0
2019-11-10 15:28:34.044849 INFO bedroom_heating: --- [R:bedroom] Initializing expression helper: PatternHelper, order = 0
2019-11-10 15:28:34.046329 INFO bedroom_heating: --- [R:bedroom] Initializing expression helper: ScheduleHelper, order = 0
2019-11-10 15:28:34.047775 INFO bedroom_heating: --- [R:bedroom] Initializing expression helper: StateHelper, order = 0
2019-11-10 15:28:34.049655 INFO bedroom_heating: --- [R:bedroom] Initializing expression helper: ThermostatExpressionHelper, order = 0
2019-11-10 15:28:34.052220 INFO bedroom_heating: --- [R:bedroom] Initializing expression helper: CustomEnvironmentHelper, order = 1000
2019-11-10 15:28:34.054596 INFO bedroom_heating: --- [R:bedroom] Executing the expression_environment script.
2019-11-10 15:28:34.067984 INFO bedroom_heating: --- [R:bedroom]     ������ => Mark(OFF, {'OVERLAY'})
2019-11-10 15:28:34.069730 INFO bedroom_heating: --- [R:bedroom] Final result: OFF
2019-11-10 15:28:34.071002 INFO bedroom_heating: --- [R:bedroom] Result markers: {'OVERLAY'}
2019-11-10 15:28:34.076204 INFO bedroom_heating: --- [R:bedroom] Result didn't change, not setting it again.
2019-11-10 15:28:34.077493 INFO bedroom_heating: --- [R:bedroom] Unchanged HA state: state='30.0', attributes={'actor_wanted_values': {'climate.air_conditioner_bedroom': '30.0'}, 'scheduled_value': 'OFF', 'rescheduling_time': 1573396843.0, 'overlay_active': False}

@thundergreen The window sensor’s attribute is there and changing it is recognized correctly, the issue here seems to be that your schedule evaluated to OFF even before opening the window. The value should be re-sent even in this case, I’ll investigate this corner case further if you open an issue on GitHub with these logs and describe the problem there.

Thank you @roschi I really appreciate your help i’ll Open an issue this evening

I’d like to calculate some times base on Google Calendar events.

I’ve seen the Dynamic Times in the docs and also looked at the expression_environment bits, but I’m not sure how to implement these.

I’m looking to activate a schedule if ‘now’ is within an hour of calendar.my_calendar.start_time for instance.

I have conditional schedules working e.g.

      - { x: 21 if app.get_state('device_tracker.me') == 'home'  else Next(), start: "08:30", end: "23:15", weekdays: "1-7"}

I just cannot get anywhere with calculating the condition based on a calculated time.

As an associated question, when are watched_entities quoted and when not?

In the docs they are quoted here but not quoted here.