Cloud Plant DB with API for PlantCard

Here we go. OpenPlantbook release 1.02

WebUI and API Release notes:

version 1.02

  • Introduction of Plant images feature. api/v1/plant/detail/ endpoint returns Plant’s image URL as image_url JSON string field.
  • Web UI is generally available for guests. Guests can search Plant DB but to get API key and plants details Signing in is required.

image_url is supposed to be dynamic link so please do not hardcode them anywhere but update from API.

Example:

curl --request GET 'https://open.plantbook.io/api/v1/plant/detail/acanthus ilicifolius/' \
--header 'Authorization: Bearer token_string'

{
    "pid": "acanthus ilicifolius",
    "display_pid": "Acanthus ilicifolius",
    "alias": "acanthus ilicifolius",
    "max_light_mmol": 2500,
    "min_light_mmol": 1200,
    "max_light_lux": 6000,
    "min_light_lux": 1500,
    "max_temp": 32,
    "min_temp": 10,
    "max_env_humid": 80,
    "min_env_humid": 30,
    "max_soil_moist": 60,
    "min_soil_moist": 15,
    "max_soil_ec": 2000,
    "min_soil_ec": 350,
    "image_url": "https://example.com/n/sdpo/b/plant-img/o/acanthus%20ilicifolius.jpg"
}

@Olen
Possibly when you get details about a plant, you can download/cache image into local folder and then refer to the local folder within component. Though, as the image can be updated on Cloud end then there should me way to re-fetch plant’s image_url from API and then new image using new URL again. The thing is in current implementation even if the url is the same the image can be different as the key to the image is pid (PlantID).

Also as users will be able to update and add more optimal environment thresholds, there should be way to refresh plant’s details from API.

I have now moved my custom component into a branch in my main home assistiant repo in preparation for creating a PR:

The logic for max/min values are:

  • If a value is configured in configuration.yaml, that value is used
  • Else if plantbook api is enabled, the values from the api is used
  • If no plant is found in the api, or api is not configured, use a hard coded default value

The logic for images are:

  • If no image: is configured in configuration.yaml generate a local url
  • Else if image is set to the string "openplantbook" in configuration.yaml, use the image URL from the API
  • Else use whatever is set in configuration.yaml

Auto-generated URLs default to http(s)://ha_external_url/local/images/plants/species.jpg
So you end up with one of:

  • image: http://10.11.12.13:8123/local/images/plants/sansevieria trifasciata.jpg
  • image: https://objectstorage.ap-sydney-1.oraclecloud.com/n/sdyd5yr3jypo/b/plant-img/o/sansevieria%20trifasciata.jpg
  • image: path/from/configuration_yaml.jpg

I have not implemented any auto-download or local caching of images, which is why I default to a local path. It is easy enough to download the image to the correct path manually when you add a new plant.

I am going to do some more cleanup, and possibly wait for the API to settle a bit more(?) before submitting a PR to the plant component itself.

I am not sure I will implement a “refresh” function for this. The data is pulled from the API each time HA starts up, and I don’t think there will be that many changes to the values.
On the other hand, I am considering adding “config flow” to the plant component, so plants can be configured from the GUI. As of now, it would be quite complicated, as you would first need to add the API client_id and secret, and then add each plant by searching the API (with a fallback if no plant is found). And then be able to add the neccesary sensors…

For now I am pretty happy that all I need to configure is the species and sensors, and the rest is taken care of by the component.

1 Like

Excellent work @Olen! Thank you!
I’m working on database editing now. Though let me know if you need any extra features for further development.

I’ve changed my mind…

I split out the openplantdb functions to a seperate integration, and made a config flow for setting up the API.
In the process I realized that the only reason this was necessary was that the API requires authentication. I am not sure why you require that for read only access, but that is another discussion…

I have also changed the plant component again, so it now takes advantage of this new openplantdb component if it is enabled and configured. This means less modifications to the plant component, and also that it could be possible to add other sources of information about plants as well, if that becomes an option later.

I’ll clean up the code some more, and add a PR for the openplantdb integration tomorrow. If (when) that is merged, I’ll add a PR to update the plant component as well.

Wow, my deepest respect for you two! Absolutely interesting! :ok_hand:

Thank you. It always annoyed me that I had to configure the max/min values for each plant in every card or sensor or automation or whatnot, and I was really considering setting up such an API myself. However, it requires some infrastructure that I do not have time to maintain at the moment. So when @slaxor did that heavy lifting, it was a great opportunity to get this “right”.

The PR for the OpenPlantbook integration is now added:

I need to rewrite parts of it and get a openplantbook-python package published in pypi first… So it will take some more time tha initially thought.

So, the pypi-package is now ready (this is a learning process…)

Next step is rebuilding the integration to use that, which shoudl be pretty easy, and then getting back to the PR…

@slaxor would it be acceptable to open the full API to everyone (read only), without having to use a client_id and secret?
It would greatly simplify the integration in HA, as we would not need a special integration just to configure the client_id and secret.

First of all, thank you @rlems for good words. I’m very glad to hear that we are bringing value to community and the product of our efforts is useful.

@Olen I’m really grateful for your contribution while enables myself and others to start using the api with home-assistant straight away.

Thank you for raising questions about anonymous read-only API access. There are number of reasons to require authentication, though the main ones are:

  1. Cloud resources are limited and I’d like to spend them only on intended use. So API serve only users who is registered and understand what API for.
  2. Another reason is security. What do I mean by that? If for example there is an DDOS attack on API or some API client misbehaves (the most likely scenario). Without authenticated access, I have no means to track the client and isolate it to prevent negative impact on API performance and cloud resources consumption.
    In addition to this in near future, API will provide write access as well so it would be more difficult to segregate anonymous requests.

Having said that I understand that authentication always brings extra layer of complexity and because of that I’m making it as simple as possible to users and developers to register and get credentials. There is potentially room for improvement here and I’m happy to implement whatever necessary to make it even easier.
I hope it makes sense and understandable. Nevertheless, I’m open to any suggestions.

I fully understand your points.
The issue is that since we need to store the client id and secret in HA, I have to create a new integration for openplantbook. However, since this integration does not provide any devices or services or entities, it sort of breaks the standard for an integration.
Without the need to store any config (client id and secrets), I could add the openplantbook api directly to the plant integration.

But I will see what the devs have to say about the openplantbook integration, and if they accept it even if it breaks some conventions.

I’m absolute novice at HASS development at this stage but logically I’d assume that openplantbook component should include all the communications call to the API and expose “species” as a service. I don’t know if I’m right here or it is too complicated to implement but I’d imagine ideally reference to a plant could be like:

species: openplantbook.champagne_mini_rose

plant:

  plant_1:
    species: openplantbook.champagne_mini_rose
    sensors:
      moisture: sensor.mi_m_80eaca88xxxx

OpenPlantbook component in return would expose plant details to the plant components.

However, I see that there could be challenge with Plant-ID but I’m happy to work it through on API end.

BTW, I have plans to clean up {pid} Plant-ID in Database and get rid of all non-letter characters such as quotes and dots and possibly spaces. It’d love to hear your opinion about this, guys.
Thanks in advance!

… I’d assume that openplantbook component should include all the communications call to the API and expose “species” as a service.

Yes. That is more or less what I have now. The Openplantbook integration handles all communication with the API. It exposes two services:

service: openplantbook.search
service_data:
  alias: Capsicum

and

service: openplantbook.get
service_data:
  species: capsicum annuum

I have started writing the documentation here:

With that in place, it is also possible to imagine something like a Lovelace card where you can search the Openplantbook and display the results. And from there it is possible to move on to create a way to configure new plants directly from the GUI.
But first and foremost I need to get the Openplantbook PR correct and added to core.

Ideally I don’t want any direct dependencies or references to the Openplantbook integration in the config of the plants. So the Plant integration will (hopefully) accept like:

plant:

  plant_1:
    species: champagne mini rose
    sensors:
      moisture: sensor.mi_m_80eaca88xxxx

And then I have a simple check in the init of the Plant integration to check if the Openplantbook integration is set up, and if it is, the Plant integration will use the Openplantbook integration get the config-data for each spieces.

Cleaning up the pids sounds like a good idea, as long as they are still unique.

Btw,

I would need a logo and icons to add here:

I can provide logo and icons if you like. When do you need them?

Great.
I need them to get the integration added I guess. So as soon as possible, but don’t rush, just do it whenever you have time.

Just hacked up a quick Plant Search using the Openplantbook integration:
OpenPlantbook screencast

It is simply using a few inputs and an entities card and a markdown card to display the plant info.
As a proof of concept, I am pretty happy with it.

(Edit: Better screenshot and improved responsetime)

Someone just got a PR for adding the configured min/max-values to the attributes of the plant entities accepted:

That is one of the steps required to have the openplantbook component do something something useful, so that is good.
The next steps are to add a two more config entries and attributes (“species” and “image”) to the plant integration and then finally include the data from the openplantbook integration if it is set up.

That’s a very cool hack @Olen! I’m impressed how quickly you deliver those! :slight_smile:
I’m wondering if HASS web UI have enough features to support plant editing UI in future and potentially plant/sensor binding as well so it will be possible to edit Plant DB directly in HASS UI w/o editing HASS config. And you can bind sensors to different plants in case you move one sensor from one plant to another. Do you think it is feasible and relatively easy to implement.

I don’t think HA is suited for modifying the data. Maybe it could be used to suggest localized names for plants, but all the other facts would be quite ugly to try modify in HA.
In a more general topic, I think that modification to the details should be moderated somehow. So 3. parties should be allowed to create “pull requests” or “suggestions”, and some moderators should be used to approve or decline changes.
And also, you are hopefully aware that many of the plant images are water marked?

Finally, I downloaded a free, publicly licensend image to use as a temporary icon for the integration:
Logo
Please feel free to replace it with a better logo as soon as you have one.