Make list of plants that need attention

Thanks to the simple examples here, I made a python script to monitor my house plants. I got many of these sensors on sale but how to make it more useful.

I wanted a human readable list of the friendly names to use in TTS notifications, and also to get better notifications (only get out the watering can if 3+ plants need to be watered).

problemPlants = 0
allproblemPlants = []
waterPlants = []
numberWater = 0
fertilizePlants = []
numberFertilize = 0
whichIcon = "mdi:help-circle-outline"

for entity_id in hass.states.entity_ids('plant'):
    state = hass.states.get(entity_id)
    if state.state == 'problem':
        problemPlants = problemPlants + 1
        allproblemPlants.append(state.name)
        problem = state.attributes.get('problem') or 'none'
        if "conductivity low" in problem:
          fertilizePlants.append(state.name)
          numberFertilize = numberFertilize + 1
        if "moisture low" in problem:
          waterPlants.append(state.name)
          numberWater = numberWater + 1

# Set icon
if problemPlants > 0:
  whichIcon = "mdi:alert-circle-outline"
else:
  whichIcon = "mdi:check-circle-outline"

# Set states
hass.states.set('sensor.water_plants', problemPlants, {
    'unit_of_measurement': 'plants',
    'friendly_name': 'Problem Plants',
    'icon': whichIcon,
    'problem_plants': allproblemPlants,
    'water': waterPlants,
    'water_number': numberWater,
    'fertilize': fertilizePlants,
    'fertilize_number': numberFertilize
})

An automation to update it any time a plant changes state:

    - alias: 'Update Plant Problems'
      trigger:
        - platform: state
          entity_id: plant.giant_philodendron, plant.giant_pothos, plant.hanging_red_pothos, plant.hanging_spider_plant, plant.kitchen_pothos, plant.palm, plant.projector_pothos, plant.rubber_plant, plant.small_philodendron, plant.window_spider_plant
      action:
        - service: python_script.plant_problems

Now easy to use the human readable lists in notifications etc

edit: now with dynamic icon and more attributes

11 Likes

Nice script! By the way, what sensors are you using?

The MiFlora ones

A TTS announcement script for watering/fertilizing status

tts_plant_info:
  alias: Announce Plant Info
  sequence:
    - service: tts.amazon_polly_say
      data_template:
        entity_id: media_player.vlc_tts
        message: >
          {% if is_state_attr('sensor.plant_problems','water_number',0) %}
          No plants need watering.
          {% elif states.sensor.plant_problems.attributes.water_number | float > 0 %}
          {{states.sensor.plant_problems.attributes.water}} need to be watered.
          {% endif %}
          {% if is_state_attr('sensor.plant_problems','fertilize_number',0) %}
          No plants need fertilizing.
          {% elif states.sensor.plant_problems.attributes.fertilize_number | float > 0 %}
          These plants {{states.sensor.plant_problems.attributes.fertilize}} need fertilizer.
          {% endif %}

How do you debug scripts? I want to use logger.warning(), but am unable to set the logger to warning for python_script. The following does not work:

logger:
  homeassistant.components.python_script: warning

tail -f home-assistant.log in a terminal window

Errors show up when the script is run, I just have whatever the default logger settings are.

My default settings are error, but would like to set it to warning or info for python_script. I can always use logger.error() during debugging, but would like to know the right approach.

In the logs, I see

2017-07-08 16:57:25 INFO (MainThread) [homeassistant.core] Bus:Handling <Event call_service[L]: domain=python_script, service=light_counter, service_data=, service_call_id=1984197328-15>
2017-07-08 16:57:25 INFO (SyncWorker_10) [homeassistant.components.python_script] Executing light_counter.py: {}
2017-07-08 16:57:25 INFO (MainThread) [homeassistant.core] Bus:Handling <Event service_executed[L]: service_call_id=1984197328-15>

homeassistant.components.python_script should work, but it is not :frowning:

This works:

logger:
  default: error
  logs:
    homeassistant.components.python_script: warning
1 Like

Hi,

Apologies for the noob questions, but I am new to python and scripts…

How would you expose the result of your python script in the front end? Would you need to create a input boolean button and then call the script with from the input boolean?

I have a plants group which is visible (25 plants - no I am not a weed farmer) and I would like to show this list in the group as default.

Thanks for any help you are able to provide.

You can use the script to create a sensor that you can then display in the frontend. For example, in this case, a new sensor sensor.plant_problems is created that can be used elsewhere.

Hi,

I have the script available to call in the services tab in developer tools. The automation is also showing up. IF I have my script woking correctly, should a new sensor appear or do I have to create a new sensor from the script?

Sorry, I am quite new to this side of HA…

Thanks

Yes, if the script creates a sensor and it is called by an automation, you should see a new sensor in your entities.

ok brilliant, thanks, got it working! THanks for all your help and hard work, I have been looking for something like this for a while… brilliant!

I have been using these scripts for the last few months and haven’t killed a house plant since :slight_smile: . I have written up the script and configuration info here:

4 Likes

I have extended this script. It now also lists plant sensors with empty batteries.

looks like this:
plantsensor

Code:

# Creates the following sensors:
#
# sensor.plants_water_number      -> Amount of plants that need to be watered
# sensor.plants_water_friendly    -> Name(s) of the plants that need water
# sensor.plants_battery_number    -> Amount of plantsensors running out of battery
# sensor.plants_battery_friendly  -> Name(s) of platsensors running out of battery
# sensor.plants_problems          -> Amount of plants which either need water or have low battery
#
#  INSPIRED BY THIS GREAT BLOGPOST
#  http://www.diyfuturism.com/making-houseplants-talk

problemPlants = 0
allproblemPlants = []
waterPlants = []
numberWater = 0
deadBatteries = []
numberdeadBatteries = 0
whichIcon = "mdi:help-circle-outline"

for entity_id in hass.states.entity_ids('plant'):
    state = hass.states.get(entity_id)
    if state.state == 'problem':
        problemPlants = problemPlants + 1
        allproblemPlants.append(state.name)
        problem = state.attributes.get('problem') or 'none'
        if "moisture low" in problem:
          waterPlants.append(state.name)
          numberWater = numberWater + 1
        if "battery low" in problem:
          deadBatteries.append(state.name)
          numberdeadBatteries = numberdeadBatteries + 1

# Set icon
if problemPlants > 0:
  whichIcon = "mdi:alert-circle-outline"
else:
  whichIcon = "mdi:check-circle-outline"

# Set states
hass.states.set('sensor.plants_problems', problemPlants, {
    'unit_of_measurement': 'Pflanzen',
    'friendly_name': 'Problempflanzen',
    'icon': whichIcon,
    'problem_plants': allproblemPlants,
    'water': waterPlants,
    'water_number': numberWater,
    'battery_change': deadBatteries,
    'battery_number': numberdeadBatteries
})

hass.states.set('sensor.plants_water_number', numberWater, {
    'unit_of_measurement': 'Pflanzen',
    'friendly_name': 'Anz. durstiger Pflanzen',
    'icon': 'mdi:water'
})

hass.states.set('sensor.plants_battery_number', numberdeadBatteries, {
    'unit_of_measurement': 'Sensoren',
    'friendly_name': 'Anz. akkuschwacher Sensoren',
    'icon': 'mdi:battery-30'
})

waterplantsList = ', '.join(waterPlants)
if waterplantsList == "":
  waterplantsList = "Keine"
hass.states.set('sensor.plants_water_friendly', waterplantsList, {
    'friendly_name': 'Durstige Pflanzen',
    'icon': 'mdi:water'
})

batteryplantsList = ', '.join(deadBatteries)
if batteryplantsList == "":
  batteryplantsList = "Keine"
hass.states.set('sensor.plants_battery_friendly', batteryplantsList, {
    'friendly_name': 'Akkuschwache Sensoren',
    'icon': 'mdi:battery-30'
})

I also have an Amazon Dashbutton running this script when pressed. It’s basically a spoken plantreport using Alexa as TTS. Like the code above it’s in german and probably doesn’t need so many elif-statements. German grammar is quite specific when it comes to singular and plural expressions :slight_smile: Have fun:

alexa_plantreport:
  alias: Alexa Pflanzenreport
  sequence:
  - service: notify.alexa
    data_template:
      message: >
        {% if states.sensor.plants_water_number.state | int == 0 and states.sensor.plants_battery_number.state | int == 0 %}
          Allen Pflanzen geht es hervorragend.
        {% elif states.sensor.plants_water_number.state | int == 1 and states.sensor.plants_battery_number.state | int == 0 %}
          Eine Pflanze braucht Wasser und zwar. {{ states.sensor.plants_water_friendly.state }}
        {% elif states.sensor.plants_water_number.state | int == 0 and states.sensor.plants_battery_number.state | int == 1 %}
          Ein Pflanzensensor benötigt eine neue Batterie und zwar. {{ states.sensor.plants_battery_friendly.state }}
        {% elif states.sensor.plants_water_number.state | int == 1 and states.sensor.plants_battery_number.state | int == 1 %}
          Eine Pflanze braucht Wasser und zwar {{ states.sensor.plants_water_friendly.state }} und ein Pflanzensensor benötigt eine neue Batterie und zwar {{ states.sensor.plants_battery_friendly.state }}.
        {% elif states.sensor.plants_water_number.state | int > 1 and states.sensor.plants_battery_number.state | int == 0 %}
          {{ states.sensor.plants_water_number.state }} Pflanzen brauchen Wasser und zwar {{ states.sensor.plants_water_friendly.state }}.
        {% elif states.sensor.plants_water_number.state | int == 0 and states.sensor.plants_battery_number.state | int > 1 %}
          {{ states.sensor.plants_battery_number.state }} Pflanzensensoren benötigen eine neue Batterie und zwar {{ states.sensor.plants_battery_friendly.state }}.
        {% elif states.sensor.plants_water_number.state | int > 1 and states.sensor.plants_battery_number.state | int == 1 %}
          {{ states.sensor.plants_water_number.state }} Pflanzen brauchen Wasser und zwar {{ states.sensor.plants_water_friendly.state }} und ein Pflanzensensor benötigt eine neue Batterie und zwar {{ states.sensor.plants_battery_friendly.state }}.
        {% elif states.sensor.plants_water_number.state | int == 1 and states.sensor.plants_battery_number.state | int > 1 %}
          Eine Pflanze braucht Wasser und zwar {{ states.sensor.plants_water_friendly.state }} und {{ states.sensor.plants_battery_number.state }} Pflanzensensoren benötigen eine neue Batterie und zwar {{ states.sensor.plants_battery_friendly.state }}.
        {% else %}
          {{ states.sensor.plants_water_number.state }} Pflanzen brauchen Wasser und zwar. {{ states.sensor.plants_water_friendly.state }} und {{ states.sensor.plants_battery_number.state }} Pflanzensensoren benötigen eine neue Batterie und zwar {{ states.sensor.plants_battery_friendly.state }}
        {% endif %}
3 Likes

Thank you, this is so cool :slight_smile:

I try run your script but how you create this list of sensors form top of the script?

Good Question! The python script needs to be triggered to update/create the sensors. I have an automation that observes the state of all my plants and whenever there is change of a plant it runs the script and updates the sensors. you can also run the python script from the dev tools in the hass ui. But here is my automation:

- alias: Pflanzenstatus Python
  initial_state: True
  trigger:
  - platform: state
    entity_id:
    - plant.avocado
    - plant.basilikum
    - plant.chilianzucht
    - plant.goldfruchtpalme
    - plant.kastanie
    - plant.rote_chili
    - plant.scotch_bonnet
    - plant.spathipyllum
  action:
  - service: python_script.plantcare

Just wanted to share the template sensor I used to create a concatenated string to display all problems.

sensor:
  - platform: template
    sensors:
      plants_detail:
        friendly_name: "Plants Detail"
        entity_id: group.all_plants
        value_template: >
          {%- if is_state('group.all_plants', 'ok') -%}
            Good
          {%- elif is_state('group.all_plants', 'problem') -%}
            {%- set problems = namespace(plants = '') -%}
            {%- for plant_id in state_attr('group.all_plants','entity_id') -%}
              {%- if is_state(plant_id, 'problem') -%}
                {%- set problems.plants = problems.plants ~ state_attr(plant_id, 'friendly_name') ~ ': ' ~ state_attr(plant_id, 'problem') ~ ', ' -%}
              {%- endif -%}
            {%- endfor -%}
            {{ problems.plants | regex_replace(', $','') }}
          {%- else -%}
            Unknown
          {%- endif %}
        icon_template: >
          {%- if is_state('group.all_plants', 'ok') -%}
            mdi:flower
          {%- elif is_state('group.all_plants', 'problem') -%}
            mdi:flower-outline
          {%- else -%}
            mdi:help-circle
          {%- endif %}

Note: The group.all_plants will be removed in 1.0.0 version of HA.

1 Like