Last active
August 2, 2020 07:46
-
-
Save blidegn/641e8a1a3922b1dfdee959164b2f665e to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import hassapi as hass | |
import datetime | |
import requests | |
import json | |
import re | |
# | |
# Ecowater App used for fetching data from Ecowater website | |
# | |
# Args: | |
# dailyruntime (fetching data at the same time every day) | |
# hourlyruntime (fetching data at the same time every hour) | |
# runevery (fetching data every number of minutes) | |
# ecowater_website | |
# ecowater_user | |
# ecowater_password | |
# ecowater_dsn | |
class GetEcowaterData(hass.Hass): | |
def initialize(self): | |
# Schedule a daily callback if dailyruntime has been defined | |
if 'dailyruntime' in self.args: | |
# Create a time object | |
dailyruntime = datetime.time(self.args["dailyruntime"][0], self.args["dailyruntime"][1], self.args["dailyruntime"][2]) | |
self.run_daily(self.run_callback, dailyruntime) | |
# Schedule hourly callback if hourlyruntime has been defined | |
if 'hourlyruntime' in self.args: | |
# Create a time object | |
hourlyruntime = datetime.time(self.args["hourlyruntime"][0], self.args["hourlyruntime"][1], self.args["hourlyruntime"][2]) | |
self.run_hourly(self.run_callback, hourlyruntime) | |
# Schedule callback every number of minutes if runevery has been defined | |
if 'runevery' in self.args: | |
# Create a time object | |
startruntime = datetime.datetime.now() + datetime.timedelta(seconds=3) | |
self.run_every(self.run_callback, startruntime, self.args["runevery"] * 60) | |
def run_callback(self, kwargs): | |
self.log("Ecowater Get Data") | |
ecowateruser = self.args["ecowater_user"] | |
# 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_user"], | |
"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(self.args["ecowater_website"]) | |
# 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(self.args["ecowater_website"], 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 | |
jsonvar = json.loads(data.text) | |
waterunit = jsonvar['water_units'] | |
waterflowunit= waterunit[0]+'PM' | |
waterunit = waterunit.lower() | |
# Delete the elements that we don't want | |
del jsonvar['water_units'] | |
del jsonvar['time'] | |
del jsonvar['recharge'] | |
# Format each piece of json data update sensor data | |
for d in jsonvar: | |
if (d == 'online') or (d == 'rechargeEnabled'): | |
sensor = 'binary_sensor.ecowater_'+d | |
if jsonvar[d]: | |
jsonvar[d]='on' | |
else: | |
jsonvar[d]='off' | |
else: | |
sensor = 'sensor.ecowater_'+d | |
choices = {'online': {"friendly_name": "Online"}, | |
'salt_level': {"friendly_name": "Salt Level"}, | |
'salt_level_percent': {"friendly_name": "Salt Level Percentage", "unit_of_measurement": "%"}, | |
'out_of_salt': {"friendly_name": "Out of salt", "icon": "mdi:clock"}, | |
'out_of_salt_days': {"friendly_name": "Out of salt days","unit_of_measurement": "days"}, | |
'water_today': {"friendly_name": "Water Today", "unit_of_measurement": waterunit, "icon": "mdi:water"}, | |
'water_avg': {"friendly_name": "Water Average", "unit_of_measurement": waterunit, "icon": "mdi:water"}, | |
'water_avail': {"friendly_name": "Water Available","unit_of_measurement": waterunit, "icon": "mdi:water"}, | |
'water_flow': {"friendly_name": "Water Flow","unit_of_measurement": waterflowunit, "icon": "mdi:water-pump"}, | |
'rechargeEnabled': {"friendly_name": "Recharge Enabled", "icon": "mdi:recycle"}} | |
sensorattributes = choices.get(d, {"friendly_name": d}) | |
# Set sensor state | |
self.set_state(sensor, state=jsonvar[d], attributes = sensorattributes) | |
# Output sensor data to log Appdaemon log file | |
self.log(sensor + ': ' + str(jsonvar[d])) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment