Ecowater softener -> how to integrate this python script?

Dear HA community,

I am still new to HA but already integrated a few things so far.
I have found that somebody coded a python script to retrieve datas from Ecowater’s softeners which I would like to use, but I cannot find how to integrate it in HA.

I have tried to add the script to the “python_scripts” directory (and added the related line in configuration.yaml), but I don’t think that’s the correct way for this script since the documentation specifies “It is not possible to use Python imports with this integration”.

I also had a look at AppDaemon, but again the script doesn’t look like the right layout with no initialize() section for example.

So I am a bit lost, and unfortunately I found no way to contact the author of the script to ask how he did the integration.

Thank you very much in advance.

Best regards,
Laurent

2 Likes

sorry to bring this one up, but I really can’t find how to implement this :confused:

Hi. this week maybe I will already have a softener and try this integration. I will be happy to help if I succeed.

How did you install Home Assistant? Are you running Home Assistant Core or Home Assistant (former hass.io), or maybe in a docker container? If you are running Home Assistant Core its just a matter of running the script as a deamon. If you are running in docker, you will need to take a diffrent approach.

Hi, thank you both for your replies.

I am running hass.io , not sure how to run the script as daemon though :confused:

I tried to run ecowater.py at the Putty terminal. I have hassio in ubuntu docker.

I think it fired correctly.

Enter the command
"user @ server: ~ $ python3 /usr/share/hassio/homeassistant/python_scripts/ecowater.py


It stops at ‘out_of_salt’ - I don’t have a device connected yet, so probably because I haven’t read anything.

Hi majdzik,

Thank you for your feedback.

I am running Hass.io, if I try to run a python command in the ssh terminal it says “command not found”. There is no “/usr/bin/python3” installed. I don’t know how Hass.io is supposed to run python scripts :confused:

Hi,
Maybe you don’t do this while logged in to the hassio terminal.
What machine do you have hassio placed on? Rapberry? Try to run the script from the main machine system (root). I made CRON to run the script every 1 min.

I used the “Terminal & SSH” add-on from the hass.io supervisor store.
I am running hass.io as a virtual machine on a VMware ESXi Supervisor. I understand the principle of running the script via python command line and add it as a cron, but to be honest I am a bit confused about how hass.io is working with it s own virtual layers and what to connect with SSH then :confused:

I’ve been trying to see if it’s possible to just use the webpage card to access wifi.ecowater.com where they have graphs for salt levels, water usage, current water flow, average daily water usage, and projected number of days left. Unfortunately I just get an error message saying the site was “blocked by response.”

So after going further and further with my HA installation, I managed to convert the python script from Kyle Johnson to an AppDaemon app :slight_smile:

Here is the code of the ecowater.py file (to be placed in the ‘appdaemon\apps’ folder) :

import mqttapi as mqtt
import datetime
from datetime import timedelta
import requests
import json
import re

#
# Retrieve data from EcoWater interface and publish to MQTT
#
# Args: ecowater_minutes, ecowater_dsn, ecowater_email, ecowater_password
#
# Credits : Thanks to Kyle Johnson for the original code (https://www.gnulnx.net/2020/02/18/ecowater-api-scraping/)
#
# Converted to AppDaemon by kalhimeo
#

class EcoWater(mqtt.Mqtt):

  def initialize(self):

    # Run every X minutes
    self.run_every(self.run_parsing, datetime.datetime.now() + timedelta(seconds=3), self.args["ecowater_minutes"] * 60)
	
  def run_parsing(self, kwargs):
	
    # Regex to match the hidden input on the initial log in page
    request_validation_re = re.compile(r'<input name="__RequestVerificationToken" type="hidden" value="(.*?)" />')

    # The serial number of your ecowater device
    dsn = { "dsn": self.args["ecowater_dsn"], }

    # The initial form data
    payload = {
        "Email" : self.args["ecowater_email"],
        "Password" : self.args["ecowater_password"],
        "Remember" : 'false'
    }
	
    # The headers needed for the JSON request
    headers = {
        'Accept': '*/*',
        'Accept-Encoding': 'gzip, deflate, br',
        'Accept-Language' : 'en-US,en;q=0.5',
        'X-Requested-With': 'XMLHttpRequest',
        'Content-Type': 'application/x-www-form-urlencoded; charset=UTF-8',
        'User-Agent': 'Mozilla/5.0 (X11; Ubuntu; Linux x86_64; rv:73.0) Gecko/20100101 Firefox/73.0'
    }

    with requests.Session() as s:
        # Initial GET request
        g = s.get('https://www.wifi.ecowater.com/Site/Login')

        # Grab the token from the hidden input
        tokens = request_validation_re.findall(g.text)

        # Add the token to the form data payload
        payload['__RequestVerificationToken'] = tokens[0]

        # Log in to the site
        login = s.post('https://www.wifi.ecowater.com/Site/Login', data=payload)

        # Add the correct Referer header
        headers['Referer'] = login.url + '/' + dsn['dsn']

        # Query the JSON endpoint for the data that we actually want
        data = s.post('https://www.wifi.ecowater.com/Dashboard/UpdateFrequentData', data=dsn, headers=headers)

        # Load the data in to json
        jsonv = json.loads(data.text)

        # Delete the elements that we don't want
        del jsonv['water_units']
        del jsonv['time']

        # Publish each piece of json data in to mqtt
        for d in jsonv:
            self.mqtt_publish('ecowater/' + d, jsonv[d])

You need to add the app in the apps.yaml and provide some parameters :

EcoWater:
  module: ecowater
  class: EcoWater
  ecowater_minutes: 60
  ecowater_dsn: 'your_ecowater_serial_number'
  ecowater_email: 'your_email_account_for_ecowater_portal'
  ecowater_password: 'your_password_for_ecowater_portal'

You can then use the MQTT data as sensors and binary sensors in HA, example :

binary_sensor:
- platform: mqtt
 name: Ecowater Online
 state_topic: "ecowater/online"
 payload_on: True
 payload_off: False

sensor:
- platform: mqtt
 name: Ecowater Salt Level
 state_topic: "ecowater/salt_level"

Available binary sensors : online, recharge, out_of_salt
Available sensors : salt_level, salt_level_percent, water_today, water_avg, water_avail, water_flow, out_of_salt_days

That’s it , have fun !

1 Like

Hi, I have the following error in AppDaemon.

WARNING AppDaemon: Unknown domain (default/mqtt) in call_service from EcoWater

How can I solve this?

Did you install MQTT broker (add-on / integration) in HA ? Did you activate and configure MQTT in AppDaemon config ?

Hi,

the broker is installed.
But what do you mean by activate and configure MQTT in AppDaemon?
I’m a Newbie to MQTT.

check your appdaemon.yaml config file in your appdaemon folder.

You should have a MQTT section in your plugins which looks like :

    MQTT:
      type: mqtt
      namespace: mqtt
      verbose: True
      client_host: mqtt_ip
      client_port: mqtt_port
      client_id: homeassistant
      client_user: username
      client_password: password

More details : https://appdaemon.readthedocs.io/en/latest/CONFIGURE.html#configuration-of-the-mqtt-plugin

Thanks, working now.
Great help.

Is there something like a beginnerguide for MQTT?

glad that it s working for you too !

I am sure there must be beginner guides, but I don t know any

The app is running good, I get the right values, but there is one warning.
Is there something I have to do about it?

WARNING AppDaemon: callback run_parsing() in EcoWater has now completed

Yes i have the same, i don t know if this is due to a debug level, or if I should have some default log line at the end of the script to confirm it s execution. I am still new with appdaemon scripting as well :slight_smile:

@kalhimeo excellent work with the script and instructions above, worked like a charm for me in first attempt.
Thanks a lot :grinning: :+1: :+1: :+1:

1 Like