Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Possible enhancement to bhyve_next_watering.py - Manual program intervals #180

Open
ComputaBloke opened this issue Apr 22, 2023 · 2 comments
Assignees

Comments

@ComputaBloke
Copy link

ComputaBloke commented Apr 22, 2023

Is your feature request related to a problem? Please describe.
I have a Orbit BHyve 6-channel, but found my watering program configuration (frequency, interval) wasn't supported by current script to calculate the a 'next watering' for the zone. So I wanted to share a rough solution which might work for others.

Describe the solution you'd like
Want to calculate the zone 'next watering' for a manual interval-based watering schedule. Equivalent to what the mobile app shows.
Since this is currently marked as *** TODO ***, here is my crack at resolving this which you can try by editing your copy of the bhyve_next_watering.py script accordingly.

Warning: This is just a start to help @sebr and the community, there are probably lots of edge cases to consider: if you have set a rain-delay, more than one program is active, more than one schedule time, or may be there are interval types which might be hours or weeks instead of days? I've also found that Orbit does not adjust for daylight savings so watering may run an hour before schedule.

Pre-requisites

  1. Standard install (per the README). HACS-installed the sebr/bhyve component, Python script integration is enabled in configuration.yaml, and bhyve_next_watering.py script downloaded and available in your <config>/python_scripts/ folder. An automation is configured to trigger the service python_script.bhyve_next_watering which you can run the script on demand for a zone's entity_id.
  2. Enable logging in configuration.yaml for python_script (set to info or debug)
# Logger config
# https://www.home-assistant.io/integrations/logger/
logger:
  default: warning
  logs:
    homeassistant.components.python_script: info # https://www.home-assistant.io/integrations/python_script [homeassistant.components.python_script.bhyve_next_watering.py]
  1. Watering program is configured in BHyve app, and can be output through the bhyve_next_watering.py (as logged on Line 89).
    When the watering program is run through a JSON formatter it should look something like this:
            logger.info("Checking manual program: %s", program)
            """
            Example output:
            {
                'enabled': True,
                'name': '3 Day Cycle',
                'is_smart_program': False,
                'start_times': ['07:10'],
                'frequency': {
                    'type': 'interval',
                    'interval': 3,
                    'interval_start_time': '2023-03-18T13:30:00.000Z'
                },
                'run_times': [{
                        'run_time': 6,
                        'station': 1
                    }
                ]
            }
            """

Calculation Logic
Given program above. Pseudo code to calculate next watering is:

  1. intervals_td = (Now - Start Date) / Configured Interval - Returns a time-delta. The 'intervals_td.days' is not really a number of days, it should hold the rounded count of waterings which would occur for the given configured interval (e.g. 'interval': 3 = every 3 days), between when the program was started, up till the 'last' watering.
  2. next_watering_tsz = Start Date + ((intervals_td.days+1) * Configured Interval)+1) - Multiplies count of intervals (+1 for next interval) with the configured interval, into a total number of days, which can then be added to the program start date, to get next watering date... but also found I needed to plus one day in my case (since I'm on plus-side of UTC)
  3. next_watering = convert the next_watering_tsz (UTC) to local timezone, and replace hours & mins with configured start time.

Implementation (fragment only, suggested script amendment)
Replace most of the existing placeholder code from Line 90 with this:

            configured_type = program.get("frequency", {}).get("type", "")
            if configured_type == "interval":
                configured_start = program.get("frequency", {}).get("interval_start_time", "")
                configured_start_tsz = dt_util.parse_datetime(str(configured_start))
                configured_intervals = program.get("frequency", {}).get("interval", 9999)
            
            configured_start_time = program.get("start_times", [])[0] # assuming only one..
            #start_time = dt_util.parse_time(configured_start_time) # Error executing script: Not allowed to access module.parse_time
            start_hours, start_mins = [int(i) for i in configured_start_time.split(":")]
            
            logger.info("intervals:%s", configured_intervals)
            
            intervals_td = (dt_util.now() - configured_start_tsz) / configured_intervals
            logger.info(f"intervals: {intervals_td.days}, ")
            
            next_watering_tsz = configured_start_tsz + datetime.timedelta(days=((intervals_td.days+1) * configured_intervals)+1)
            next_watering = dt_util.as_local(next_watering_tsz).replace(hour=start_hours, minute=start_mins)
            logger.info(f"next_watering: {configured_start_tsz} + ({(intervals_td.days+1)} * {configured_intervals}) = {next_watering_tsz} at start time {configured_start_time} = {next_watering}")

Resulting program and calculation will be logged when you run the Automation.

@ComputaBloke
Copy link
Author

ComputaBloke commented Apr 22, 2023

Further, I was able to display the resulting sensor timestamp value using a HACS custom:template-entity-row, with this example template:

type: entities
entities:
  - entity: weather.home
    state_color: true
    name: Forecast precipitation
    icon: mdi:weather-rainy
  - type: custom:template-entity-row
    icon: mdi:watering-can
    name: Next watering scheduled
    state: >-
      {{ (states('sensor.lhs_veges_next_watering') | as_datetime).timestamp() |
      timestamp_custom('%d %b at %H:%M') }}

image

@bakernigel
Copy link

Works well for my 6 Zone B-Hyve. Found I didn't need the plus one day for next_watering_tsz in my case (I'm on negative-side of UTC).

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants