PlantLink Integration

I’d really like to add plantlink integration into HA. PlantLink is a platform designed to monitor your indoor and outdoor plants and alert you when the plant needs water. It consists of 2 components. A sensor, that’s placed directly in the plants soil, that takes the readings, and a base station that takes those readings and transfers them to the plantlink servers/app. The devices communicate via zigbee radios, and are fairly easy to use and setup, and relatively low cost. Their website is here: http://myplantlink.com/

Plantlink offers an API to check the status of your plants, pull values, etc. I’ve successfully added plantlink to openhab via http, parsing the returned values via JSON, and in come cases converting the output to something usable. The API is documented here: https://market.mashape.com/danwiding/plantlink

I’m wondering if it would be possible to add a plantlink component to HA?

I’m not exactly sure how to go about this, or even where to start.
Any suggestions would be greatly appreciated.

This would be pretty cool, I have a Plantlink system that I have yet to tinker with. But alas, I don’t think that I can offer any help, coding is not my forte. I did see a few python modules on github that states that it can communicate with the hub.

I would also be interested in learning how you connected to OpenHAB. Any chances that you could show a few examples?

@berniebl If you wouldn’t mind, would you link the python modules here, so we have them?

The OH integration was a bit harry, but it worked. Basically I was polling the http api looking at a particular plant, then using JSONPATH to parse for a decimal/string. it got interesting when I tried to pull the “updated” & “water_needed” date & time, because they’re in epoch. So I had an automation rule fire that would convert the epoch to something I could work with.

Here’s a few examples from my items file in OH:

String Plant6           		"[%s]"            		(Plant6)        { http="<[http://dashboard.myplantlink.com/api/v1/plants/XXXXXXXXXX{authorization=Basic XXXXXXXXXXXXXXXXXXXXXXXXXXX=}:3600000:JSONPATH($..name[0])]" }
String Plant6_Updated           "Updated [%s]"            (Plant6)
Number Plant6_Updated_Raw       "[%d]"                          				{ http="<[http://dashboard.myplantlink.com/api/v1/plants/XXXXXXXXXX{authorization=Basic XXXXXXXXXXXXXXXXXXXXXXXXXXX=}:1800000:JSONPATH($..last_measurements.updated[0])]" }
Number Plant6_Fuel              "Fuel [%.4f]"             (MyOpenHAB, Plant6)        { http="<[http://dashboard.myplantlink.com/api/v1/plants/XXXXXXXXXX{authorization=Basic XXXXXXXXXXXXXXXXXXXXXXXXXXX=}:1800000:JSONPATH($..last_measurements.plant_fuel_level[0])]" } 

If you look into the API documentation above, it’ll help you get your auth token. I then used Postman (chrome add-on) to pull the data from the API, and used that to build the above URL’s for each element. Figuring out the JSONPATH was a bit tricky, and honestly just involved a lot of trial and error. If you want the full example, including rules and everything let me know, I’ll toss it up on my site. (Rather not post it here, as it’s OH specific)

Thanks for the OpenHab examples, I may take you up on getting the entire set of rules etc. Do you know if everything would work with OpenHab 2? I am still undecided between Home Assistant and OpenHab at this time and also undecided between getting Plantlink going or trying the Xiaomi Plant sensors.

As far as Python libraries, I will list a few things that I found, again, since I am not a coder, I may think that it’s a library that can be used, but it may just be a single module, you may know better than I for these thing. Not all are from Github either.

This first one seems promising but never was able to download it for some reason:
https://www.sdks.io/SDK/View/plantlink-2

This one is from OSO Technologies. The appengine seems to have something that could be useful
https://github.com/OsoTech

And there is some code here that someone may be able to adapt.

Searching for “Plantlink” on Github also brings up a few other forks including this good article.

Hope any of this helps

Just found this.

Working perl code to poll data:
https://osotech.zendesk.com/hc/en-us/community/posts/205898146-Working-Perl-code-for-querying-API

There’s quite a few projects on github for the plantlink!

Most of them allow connection to the Smartthings hub.

Sheesh man, I answer your stuff on OpenHAB… and now here too? :wink:

# configuration.yaml
sensor:
  - platform: rest
   resource: http://dashboard.myplantlink.com/api/v1/plants/[Plant Key Here]
   method: GET
   authentication: basic
   headers:
     Authorization: Basic [your code here]
   verify_ssl: false
   name: Plant Status
   value_template: '{{ value_json.status }}'

This matches the JSON output:

{
  "plant_type": {
    "common_names": [
      "XXX",
      "XXX"
    ],
    "name": "XXX",
    "key": XXXX
  },
  "status": "Online",
[ ... ]

For the ‘last_measurement’ values your value_template will be:

Moisture:
value_template: '{{ value_json.last_measurements[0]["moisture"] }}'

Signal:
value_template: '{{ value_json.last_measurements[0]["signal"] }}'

Battery %:
value_template: '{{ value_json.last_measurements[0]["battery"] }}'

etc.

1 Like

Updated:

# configuration.yaml
sensor:
  - platform: rest
    resource: http://dashboard.myplantlink.com/api/v1/plants/[your PlantKey]
    method: GET
    authentication: basic
    headers:
      Authorization: Basic [your Auth]=
    verify_ssl: false
    name: Plant0 Status
    value_template: '{{ value_json.status }}'
  - platform: rest
    resource: http://dashboard.myplantlink.com/api/v1/plants/[your PlantKey]
    method: GET
    authentication: basic
    headers:
      Authorization: Basic [your Auth]=
    verify_ssl: false
    name: Plant0 Moisture
    sensor_class: moisture
    unit_of_measurement: '%'
    value_template: '{{ float(value_json.last_measurements[0]["moisture"]) * 100 | round(3) }}'
  - platform: rest
    resource: http://dashboard.myplantlink.com/api/v1/plants/[your PlantKey]
    method: GET
    authentication: basic
    headers:
      Authorization: Basic [your Auth]=
    verify_ssl: false
    name: Plant0 Fuel
    value_template: '{{ value_json.last_measurements[0]["plant_fuel_level"] | round(3) }}'
  - platform: rest
    resource: http://dashboard.myplantlink.com/api/v1/plants/[your PlantKey]
    method: GET
    authentication: basic
    headers:
      Authorization: Basic [your Auth]=
    verify_ssl: false
    name: Plant0 Signal
    unit_of_measurement: '%'
    value_template: '{{ float(value_json.last_measurements[0]["signal"]) * 100 | round(3) }}'
  - platform: rest
    resource: http://dashboard.myplantlink.com/api/v1/plants/[your PlantKey]
    method: GET
    authentication: basic
    headers:
      Authorization: Basic [your Auth]=
    verify_ssl: false
    name: Plant0 Battery
    unit_of_measurement: '%'
    value_template: '{{ float(value_json.last_measurements[0]["battery"]) * 100 | round(3) }}'
  - platform: rest
    resource: http://dashboard.myplantlink.com/api/v1/plants/[your PlantKey]
    method: GET
    authentication: basic
    headers:
      Authorization: Basic [your Auth]=
    verify_ssl: false
    name: Plant0 Last Updated
    value_template: '{{ value_json.last_measurements[0]["updated"] | timestamp_local }}'
  - platform: rest
    resource: http://dashboard.myplantlink.com/api/v1/plants/[your PlantKey]
    method: GET
    authentication: basic
    headers:
      Authorization: Basic [your Auth]=
    verify_ssl: false
    name: Plant0 Next Water
    value_template: '{{ value_json.last_measurements[0]["predicted_water_needed"] | timestamp_local }}'

I’ve been working with this and got the following warnings in the logs:

Feb 17 10:52:06 droid hass[31103]: /usr/local/lib/python3.5/dist-packages/requests/packages/urllib3/connectionpool.py:852: InsecureRequestWarning: Unverified HTTPS request is being made. Adding certificate verification is strongly advised. See: https://urllib3.readthedocs.io/en/latest/advanced-usage.html#ssl-warnings
Feb 17 10:52:06 droid hass[31103]:   InsecureRequestWarning)
Feb 17 10:52:06 droid hass[31103]: /usr/local/lib/python3.5/dist-packages/requests/packages/urllib3/connectionpool.py:852: InsecureRequestWarning: Unverified HTTPS request is being made. Adding certificate verification is strongly advised. See: https://urllib3.readthedocs.io/en/latest/advanced-usage.html#ssl-warnings
Feb 17 10:52:06 droid hass[31103]:   InsecureRequestWarning)
Feb 17 10:52:06 droid hass[31103]: /usr/local/lib/python3.5/dist-packages/requests/packages/urllib3/connectionpool.py:852: InsecureRequestWarning: Unverified HTTPS request is being made. Adding certificate verification is strongly advised. See: https://urllib3.readthedocs.io/en/latest/advanced-usage.html#ssl-warnings
Feb 17 10:52:06 droid hass[31103]:   InsecureRequestWarning)
Feb 17 10:52:06 droid hass[31103]: /usr/local/lib/python3.5/dist-packages/requests/packages/urllib3/connectionpool.py:852: InsecureRequestWarning: Unverified HTTPS request is being made. Adding certificate verification is strongly advised. See: https://urllib3.readthedocs.io/en/latest/advanced-usage.html#ssl-warnings
Feb 17 10:52:06 droid hass[31103]:   InsecureRequestWarning)
Feb 17 10:52:06 droid hass[31103]: /usr/local/lib/python3.5/dist-packages/requests/packages/urllib3/connectionpool.py:852: InsecureRequestWarning: Unverified HTTPS request is being made. Adding certificate verification is strongly advised. See: https://urllib3.readthedocs.io/en/latest/advanced-usage.html#ssl-warnings
Feb 17 10:52:06 droid hass[31103]:   InsecureRequestWarning)
Feb 17 10:52:06 droid hass[31103]: /usr/local/lib/python3.5/dist-packages/requests/packages/urllib3/connectionpool.py:852: InsecureRequestWarning: Unverified HTTPS request is being made. Adding certificate verification is strongly advised. See: https://urllib3.readthedocs.io/en/latest/advanced-usage.html#ssl-warnings
Feb 17 10:52:06 droid hass[31103]:   InsecureRequestWarning)
Feb 17 10:52:06 droid hass[31103]: /usr/local/lib/python3.5/dist-packages/requests/packages/urllib3/connectionpool.py:852: InsecureRequestWarning: Unverified HTTPS request is being made. Adding certificate verification is strongly advised. See: https://urllib3.readthedocs.io/en/latest/advanced-usage.html#ssl-warnings
Feb 17 10:52:06 droid hass[31103]:   InsecureRequestWarning)
Feb 17 10:52:06 droid hass[31103]: /usr/local/lib/python3.5/dist-packages/requests/packages/urllib3/connectionpool.py:852: InsecureRequestWarning: Unverified HTTPS request is being made. Adding certificate verification is strongly advised. See: https://urllib3.readthedocs.io/en/latest/advanced-usage.html#ssl-warnings

If I change “verify_ssl: true”, the sensors don’t show up at all, and I get this in the logs:

Feb 17 11:10:58 droid hass[31474]: INFO:homeassistant.components.sensor:Setting up sensor.rest
Feb 17 11:10:58 droid hass[31474]: message repeated 7 times: [ INFO:homeassistant.components.sensor:Setting up sensor.rest]
Feb 17 11:10:58 droid hass[31474]: ERROR:homeassistant.components.sensor.rest:Error fetching data: <PreparedRequest [GET]>
Feb 17 11:10:58 droid hass[31474]: ERROR:homeassistant.components.sensor.rest:Unable to fetch REST data
Feb 17 11:10:58 droid hass[31474]: ERROR:homeassistant.components.sensor.rest:Error fetching data: <PreparedRequest [GET]>
Feb 17 11:10:58 droid hass[31474]: message repeated 2 times: [ ERROR:homeassistant.components.sensor.rest:Error fetching data: <PreparedRequest [GET]>]
Feb 17 11:10:58 droid hass[31474]: ERROR:homeassistant.components.sensor.rest:Unable to fetch REST data
Feb 17 11:10:58 droid hass[31474]: message repeated 2 times: [ ERROR:homeassistant.components.sensor.rest:Unable to fetch REST data]
Feb 17 11:10:58 droid hass[31474]: ERROR:homeassistant.components.sensor.rest:Error fetching data: <PreparedRequest [GET]>
Feb 17 11:10:58 droid hass[31474]: message repeated 3 times: [ ERROR:homeassistant.components.sensor.rest:Error fetching data: <PreparedRequest [GET]>]
Feb 17 11:10:58 droid hass[31474]: ERROR:homeassistant.components.sensor.rest:Unable to fetch REST data
Feb 17 11:10:58 droid hass[31474]: message repeated 3 times: [ ERROR:homeassistant.components.sensor.rest:Unable to fetch REST data]

Trying to figure out why, anyone else run into this?

I know customizing is more of a personal choice, but here’s an example:

sensor.plant0_name:
    friendly_name: Type
    icon: mdi:leaf
sensor.plant0_status:
    friendly_name: Status
    icon: mdi:power
sensor.plant0_moisture:
    friendly_name: Moisture
    icon: mdi:water
sensor.plant0_fuel:
    friendly_name: Fuel
    icon: mdi:flash
sensor.plant0_battery:
    friendly_name: Battery
    icon: mdi:battery
sensor.plant0_signal:
    friendly_name: Signal
    icon: mdi:signal-variant
sensor.plant0_next_water:
    friendly_name: Need Water
    icon: mdi:update
sensor.plant0_last_updated:
    friendly_name: Updated
    icon: mdi:update

Been debugging the moisture reading for a while, finally found something that works!
In the above code, replace:

value_template: ‘{{ float(value_json.last_measurements[0][“moisture”]) * 100 | round(3) }}’

With:

value_template: ‘{{ (value_json.last_measurements[0][“moisture”]) | round(3) * 100 }}’

So instead of getting a moisture reading of: 23.04293324318214%
You’ll get a moisture reading of: 23.0%

Cheers!

Updated the Status value template, now it actually reads the plant status such as Too Dry, or Optimal, as opposed to 0…4.

Simple replace:

value_template: '{{ value_json.status }}' 

With:

value_template: >
           {% if value_json.status == 0 %}
             Needs Water
           {% elif value_json.status == 1 %}
             Dry
           {% elif value_json.status == 2 %}
             Good
           {% elif value_json.status == 3 %}
             Good
           {% elif value_json.status == 4 %}
             Too Wet
           {% else %}
             value_json.status
           {% endif %} 

Please note; I haven’t been able to verify all the status codes, so if you get something other than Too Dry, Dry, Optimal, Wet, Too Wet, please let me know.

1 Like

Status values translated to names can be found here, roughly half way down:

How has this been working? It’s pulling the data from the cloud?

It’s been working great for the most part, there’s been a few instances where the plantlink dashboard API has been unavailable, but that’s pretty rare. To answer your question, yes, it’s pulling data from the cloud. As far as I can tell, there’s no way to poll data locally from the plantlink hub thing, but I haven’t had time to reverse engineer it yet.

Cool gonna try I bought like 20 of these things when they went on sale at Home Depot!
On smarthings they where using them direct connected to smarthings hub instead of the hub they come with. Maybe look at how they did that? I got a SamrtThings hub laying around here also so may just try that also.

Hey all just finally started using this myself :slight_smile: are there any code updates to the rest sensor? I think maybe the status value isn’t right? Thanks for the write up as well it was very helpful to get things going.

Edit: it looks like value_json.status is now being sent back as a string so I just needed to wrap the numbers in quotes and its working. Thank you for the post and updates @xstrex! I wonder if we can maybe just add this to zha or deconz for local integration :slight_smile:

1 Like