Adding input_number to input_timedate for alarm clock

Hello,

I’m trying to create an alarm clock that can be easily adjusted by using an input_number.

Currently I have the alarm clock setup so when I log a feeding (for new born), it will automatically adjust the alarm clock 2 hours into the future. This part works perfectly, the issue is that it’s static, meaning its always two hours. Sometimes though we may want to have the alarm be 2.5 or 3 hours into the future.

My goal, is to use an input_number to dynamically set the time between feedings. For example, lets say I log a feeding at 2pm. The next part of the automation should check the current time, then add the state of the input_number to be the next feeding time. So if its 2pm and the input_number is set to 3, the next feeding time would be 5pm.

I also want to make sure any time the input_number is adjusted it automatically adjusts the next feeding time. Following the same example above, the next feeding time is 5pm but later I decide to change the input_number to 3.5, now the next feeding time should be 5:30pm. (btw I only plan on doing half hour increments).

I hope this post makes sense to someone that can help me. I know dealing with time is often a pain. Maybe I’m going about this completely wrong and someone can steer me in the right direction.

How my current alarm clock works.

Adding a feeding entry triggers this script, which adjusts the next feeding time 2 hours in the future.

update_next_feed:
  alias: Update Next Feed
  mode: single
  sequence:
    - service: input_datetime.set_datetime
      data:
        datetime: '{{ (now().strftime("%s")|int +7200|int) |timestamp_custom("%Y-%m-%d %H:%M:%S", false) }}'
      target:
        entity_id: input_datetime.feeding_time
    - service: notify.caspillers
      data:
        message: "clear_notification"
        data:
          tag: "feed"

Then in order for the alarm to trigger I use a sensor to convert the input_datetime.feeding_time into hours and minutes.

- platform: template
  sensors:
    convert_feedtime:
      friendly_name: Convert Feed Time
      value_template: "{{ states.input_datetime.feeding_time.attributes.timestamp  | timestamp_custom('%H:%M') }}"

Followed by another sensor that compares the current time to the sensor above sensor.covert_feedtime. When this sensor becomes true, the alarm clock is triggered to notify me.

- platform: template
  sensors:
    compare_feedtime:
      friendly_name: Compare Feed Time
      value_template: "{{states('sensor.time') == states('sensor.convert_feedtime')}}" 

I use something similar in my lawn watering. Here is the automation and entities.

- id: 'xxxxx'
  alias: Water Lawn with repeat
  description: Water all zones with repeat
  trigger:
  - platform: time
    at:
    - input_datetime.cycle1
    - input_datetime.cycle2
    - input_datetime.cycle3
    - input_datetime.cycle4
    - input_datetime.cycle5
    - input_datetime.cycle6
  condition:
  - condition: state
    entity_id: sensor.watering_days
    state: '0'
  - condition: state
    entity_id: input_boolean.run_irrigation
    state: 'on'
  action:
  - repeat:
      count: '11'
      sequence:
      - variables:
          zone: switch.zone_{{ repeat.index }}
      - service: switch.turn_on
        target:
          entity_id: '{{ zone }}'
      - delay:
          minutes: '{{ states(''input_number.zone'' ~ repeat.index) | int }}'
      - service: switch.turn_off
        target:
          entity_id: '{{ zone }}'
  mode: single

Here is a screenshot of setting the values.

You could modify your code like this

 sequence:
    - service: input_datetime.set_datetime
      data:
        datetime: "{{ (now().strftime("%s")|int + (states('input_number.my_minutes') * 60) | int ) | timestamp_custom("%Y-%m-%d %H:%M:%S", false) }}"

edit - fixed single to double quotes

Thank you very much for your reply. When I enter that code into my script, I’m getting the following error. I’m failing to find the issue.

Error loading /config/configuration.yaml: while parsing a block mapping
in "/config/scripts.yaml", line 10, column 9
expected <block end>, but found '<scalar>'
in "/config/scripts.yaml", line 10, column 60

Fully updated script

update_next_feed:
  alias: Update Next Feed
  mode: single
  sequence:
    - service: input_datetime.set_datetime
      data:
        datetime: '{{ (now().strftime("%s")|int + (states('input_number.time_between_feedings') * 60) | int ) | timestamp_custom("%Y-%m-%d %H:%M:%S", false) }}'
      target:
        entity_id: input_datetime.feeding_time
    - service: notify.caspillers
      data:
        message: "clear_notification"
        data:
          tag: "feed"

Try this and see if it fixes

datetime: "{{ (now().strftime("%s")|int + (states('input_number.time_between_feedings') | int * 60) ...

states will be a string and you need a number

edit - changed single to double quotes

Ok, I fixed that first error by changing the outside quotes to double quotes and all the inside quotes to single.

Now when I run the script I’m getting the following error in the logs.

Update Next Feed: Error executing script. Error for call_service at pos 1: Error rendering data template: TypeError: unsupported operand type(s) for +: 'int' and 'str'

I’ll try the code you just posted real quick.

Sorry for the typo’s

Awesome, ok got that part to work. Maybe you can help on the next part to.

Anytime input_number.time_between_feedings is changed, I’d like it to update input_datetime.feeding_time. I’m sure I can do this by creating an automation that, anytime the input_number is changed, run the script again. Only problem with that is it will update the time based on the time I changed the input_number. So for example if I can the input_number an hour after the feeding was logged, it will adjust the input_datetime based on the hour later time…if that makes sense.

Here is my working code so far

update_next_feed:
  alias: Update Next Feed
  mode: single
  sequence:
    - service: input_datetime.set_datetime
      data:
        datetime: "{{ (now().strftime('%s')|int + (states('input_number.time_between_feedings') | int * 3600) | int ) | timestamp_custom('%Y-%m-%d %H:%M:%S', false) }}"
      target:
        entity_id: input_datetime.feeding_time
    - service: notify.caspillers
      data:
        message: "clear_notification"
        data:
          tag: "feed"

I think what you need is a template sensor so that when you change the input_number you modify the input_datetime.

see here:

You will need to store your old value.

You can do it by using a time pattern that stores the input number every hour.

- id: 'xxxxxx'
  alias: 'Record state every x hours '
  description: Record the state
  trigger:
  - platform: time_pattern
    hours: /1
  condition: []
  action:
  - service: input_text.set_value
    target:
      entity_id: input_number.time_between_feedings_save
    data:
      value: "{{ states('input_number.time_between_feedings') }}"
  mode: single

@AllHailJ Thank you very much with your help so far.

I know where I can pull the data I need to get the correct value when the input_number is changed. The problem is I don’t know how I can implement that into my code.

I’m going to create a second script that, when the input_number is changed after a feeding has been logged, it will update the next feeding based on sensor.babys_last_feeding. Can you help me using this value (instead of now) + the input_number?

I tried the code below in the templates but am getting the value 1970-01-01 01:00:00 returned.

{{ (states('sensor.ayla_last_feeding')|int + (states('input_number.time_between_feedings') |int * 3600) | int ) | timestamp_custom('%Y-%m-%d %H:%M:%S', false) }}

I think part of the problem could be that the value of sensor.ayla_last_feeding needs to be converted somehow. Currently the value looks like this '2022-04-15T15:39:00-06:00'

What is the format of sensor.ayla_last_feeding? Is it a string datetime?

if it is your can do

{{ ( states('sensor.ayla_last_feeding')| as_timestamp + (states('input_number.time_between_feedings') | int *60)) | as_datetime }}

The as_timestamp will change the string to an integer with 0 at 1/1/1970 at midnight. as_datetime will change it back to a string in the proper format.

Are you familiar with developer tools? If not go to template under developer tools and try it.

@AllHailJ The value of sensor.ayla_last_feeding looks like 2022-04-15 15:39:00

When I put the code below in the developer tools templates, the calculation is off. I currently have the input_number set to 1, which should return 2022-04-15 16:39:00+00:00 (1 hour from the last feeding) but instead it returns 2022-04-15 22:39:00+00:00 (7 hours from the last feeding).

{{ ( states('sensor.ayla_last_feeding')| as_timestamp + (states('input_number.time_between_feedings') | int *3600)) | as_datetime }}

I did have to change *60 to *3600 because when I changed the input_number the minute was changing instead of the hour.

When I do essentially the same thing in templates I get

I am using now() for sensor.ayla_last_feeding and input_number.zone1 for input_number.time_between_feedings. The reason for 60 was I use my input number as minutes - habit.

But as you can see the two times are 5 hours off. Also I changed to float in case you wanted decimal hours 1.25, 1.5, 1.75 etc.

I just realized what the problem is. It is returning UTC time and it needs to be local.

try this:

{{ as_local( ( states('sensor.ayla_last_feeding')| as_timestamp + (states('input_number.time_between_feedings') | int *3600)) | as_datetime )}}

Here it is in the developer for me.

1 Like

FWIW, the input_datetime.set_datetime service accepts a timestamp so the template can be simplified (by eliminating the conversion to a datetime string).

  sequence:
    - service: input_datetime.set_datetime
      data:
        timestamp: "{{ (now().timestamp() + states('input_number.time_between_feedings') | int(0) * 60) | int(0) }}"
      target:
        entity_id: input_datetime.feeding_time

The template final int(0) is optional; it merely lops off the seconds in the time.

Yes!!! This was it, thank you so much for your help. Man I can’t thank you enough. Really this helps out our ability to easily modify the feeding schedule so nicely.
Thinking about it more, I only need this code, the first one that includes now() is not needed since when I log a feeding, it sets the proper time stamp.

My pleasure and enjoy your newborn!! You and your partner need all the sleep you can get. I remember those days!