Add Flume Sensor

Add support for Flume API and sensor
This commit is contained in:
ChrisMandich
2019-10-03 23:51:09 -07:00
parent 5c01dd483f
commit 95832ae388
3 changed files with 201 additions and 0 deletions

View File

@@ -0,0 +1 @@
"""The Flume component."""

View File

@@ -0,0 +1,8 @@
{
"domain": "Flume",
"name": "Flume, Chris Mandich",
"documentation": "tbd",
"dependencies": [],
"codeowners": ["@ChrisMandich"],
"requirements": []
}

View File

@@ -0,0 +1,192 @@
"""Sensor for displaying the number of result from Flume."""
import base64
from datetime import datetime, timedelta
import json
import logging
import requests
import voluptuous as vol
from homeassistant.components.sensor import PLATFORM_SCHEMA
from homeassistant.const import CONF_NAME, CONF_USERNAME, CONF_PASSWORD
import homeassistant.helpers.config_validation as cv
from homeassistant.helpers.entity import Entity
_LOGGER = logging.getLogger(__name__)
DEFAULT_NAME = "Flume Sensor"
CONF_CLIENT_ID = "client_id"
CONF_CLIENT_SECRET = "client_secret"
CONF_DEVICE_ID = "device_id"
SCAN_INTERVAL = timedelta(minutes=1)
PLATFORM_SCHEMA = PLATFORM_SCHEMA.extend(
{
vol.Required(CONF_USERNAME): cv.string,
vol.Required(CONF_PASSWORD): cv.string,
vol.Required(CONF_CLIENT_ID): cv.string,
vol.Required(CONF_CLIENT_SECRET): cv.string,
vol.Required(CONF_DEVICE_ID): cv.string,
vol.Optional(CONF_NAME, default=DEFAULT_NAME): cv.string,
}
)
def setup_platform(hass, config, add_entities, discovery_info=None):
"""Set up the Flume sensor."""
username = config.get(CONF_USERNAME)
password = config.get(CONF_PASSWORD)
client_id = config.get(CONF_CLIENT_ID)
client_secret = config.get(CONF_CLIENT_SECRET)
device_id = config.get(CONF_DEVICE_ID)
name = config.get(CONF_NAME)
Flume = FlumeData(
username, password, client_id, client_secret, device_id, SCAN_INTERVAL
)
try:
Flume.update()
except Exception as error:
_LOGGER.error("Unable to update: %s", error)
return False
add_entities([FlumeSensor(Flume, name)], True)
class FlumeSensor(Entity):
"""Representation of the Flume sensor."""
def __init__(self, Flume, name):
"""Initialize the Flume sensor."""
self.Flume = Flume
self._name = name
self._state = None
self._unit_of_measurement = "GALLONS"
@property
def name(self):
"""Return the name of the sensor."""
return self._name
@property
def state(self):
"""Return the state of the sensor."""
return self._state
@property
def unit_of_measurement(self):
"""Return the unit the value is expressed in."""
return self._unit_of_measurement
def update(self):
"""Get the latest data and updates the states."""
self.Flume.update()
self._state = self.Flume.value
class FlumeData:
"""Get the latest data and update the states."""
def __init__(
self, username, password, client_id, client_secret, device_id, scan_interval
):
"""Initialize the data object."""
self._username = username
self._password = password
self._client_id = client_id
self._client_secret = client_secret
self._device_id = device_id
self._scan_interval = scan_interval
self._token = self.getToken()
self._user_id = self.getUserId()
self._bearer = self.getBearer()
self.value = None
self.update()
def getToken(self):
"""Return authorization token for session."""
url = "https://api.flumetech.com/oauth/token"
payload = (
'{"grant_type":"password","client_id":"'
+ self._client_id
+ '","client_secret":"'
+ self._client_secret
+ '","username":"'
+ self._username
+ '","password":"'
+ self._password
+ '"}'
)
headers = {"content-type": "application/json"}
response = requests.request("POST", url, data=payload, headers=headers)
_LOGGER.debug("Token Payload: %s", payload)
_LOGGER.debug("Token Response: %s", response.text)
if response.status_code == 200:
return json.loads(response.text)["data"]
else:
raise Exception(
"getToken Response Code not Successful. Returned {}".format(
response.status_code
)
)
def getUserId(self):
"""Return User ID for authorized user."""
json_token_data = self._token[0]
return json.loads(
base64.b64decode(json_token_data["access_token"].split(".")[1])
)["user_id"]
def getBearer(self):
"""Return Bearer for Authorized session."""
return self._token[0]["access_token"]
def update(self):
"""Return updated value for session."""
url = (
"https://api.flumetech.com/users/"
+ str(self._user_id)
+ "/devices/"
+ str(self._device_id)
+ "/query"
)
now = datetime.now()
since_datetime = (now - self._scan_interval).strftime("%Y-%m-%d %H:%M:00")
until_datetime = now.strftime("%Y-%m-%d %H:%M:00")
queryDict = {
"queries": [
{
"since_datetime": since_datetime,
"until_datetime": until_datetime,
"bucket": "MIN",
"request_id": "update",
"units": "GALLONS",
}
]
}
headers = {"authorization": "Bearer " + self._bearer + ""}
response = requests.post(url, json=queryDict, headers=headers)
_LOGGER.debug("Update URL: %s", url)
_LOGGER.debug("Update headers: %s", headers)
_LOGGER.debug("Update queryDict: %s", queryDict)
_LOGGER.debug("Update Response: %s", response.text)
if response.status_code == 200:
self.value = json.loads(response.text)["data"][0]["update"][0]["value"]
else:
raise Exception(
"getDevices Response Code not Successful. Returned {}".format(
response.status_code
)
)