Skip to content

Commit

Permalink
Fixed broken days value for usage sensor, updated README and tidied u…
Browse files Browse the repository at this point in the history
…p a bit
  • Loading branch information
linsvensson committed Apr 8, 2022
1 parent 2a168f7 commit 90d1bb0
Show file tree
Hide file tree
Showing 5 changed files with 196 additions and 237 deletions.
24 changes: 10 additions & 14 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,26 +1,22 @@
# sensor.greenely
[![GitHub last commit](https://img.shields.io/github/last-commit/linsvensson/sensor.greenely)](https://github.com/linsvensson/sensor.greenely)
![GitHub release (latest by date)](https://img.shields.io/github/v/release/linsvensson/sensor.greenely?color=pink&style=for-the-badge)
![GitHub last commit](https://img.shields.io/github/last-commit/linsvensson/sensor.greenely?color=pink&style=for-the-badge)

[![hacs_badge](https://img.shields.io/badge/HACS-Custom-41BDF5.svg?color=pink&style=for-the-badge)](https://github.com/hacs/integration)

_Custom component to get usage data and prices from [Greenely](https://www.greenely.se/) for [Home Assistant](https://www.home-assistant.io/)._

Because Greenely doesn't have an open api yet, we are using the Android user-agent to access data.
Data is fetched every hour.

## Installation
### Install with HACS (recommended)
- Add the url to the repository as a custom integration.

### Manual
1. Using the tool of choice open the directory (folder) for your HA configuration (where you find `configuration.yaml`).
2. If you do not have a `custom_components` directory (folder) there, you need to create it.
3. In the `custom_components` directory (folder) create a new folder called `greenely`.
4. Download _all_ the files from the `custom_components/greenely/` directory (folder) in this repository.
5. Place the files you downloaded in the new directory (folder) you created.

Using your HA configuration directory (folder) as a starting point you should now also have this:

```text
custom_components/greenely/__init__.py
custom_components/greenely/sensor.py
custom_components/greenely/manifest.json
```
- Copy directory `custom_components/greenely` to your `<config dir>/custom_components` directory.
- Configure with config below.
- Restart Home-Assistant.

## Configuration
Add the sensor `- platform: greenely` to your HA configuration.
Expand Down
100 changes: 100 additions & 0 deletions custom_components/greenely/api.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,100 @@
"""Greenely API"""
import logging
from datetime import datetime, timedelta
import requests
import json

_LOGGER = logging.getLogger(__name__)

class GreenelyApi:
def __init__(self, email, password):
self._jwt = ''
self._url_check_auth = 'https://api2.greenely.com/v1/checkauth'
self._url_login = 'https://api2.greenely.com/v1/login'
self._url_retail = 'https://api2.greenely.com/v2/retail/overview'
self._url_data = 'https://api2.greenely.com/v3/data/'
self._url_sold = 'https://api2.greenely.com/v1/facilities/'
self._url_spot_price = 'https://api2.greenely.com/v1/facilities/'
self._url_facilities = 'https://api2.greenely.com/v1/facilities/primary?includes=retail_state&includes=consumption_limits&includes=parameters'
self._headers = {'Accept-Language':'sv-SE',
'User-Agent':'Android 2 111',
'Content-Type': 'application/json; charset=utf-8',
'Authorization':self._jwt}
self._email = email
self._password = password
self._facility_id = ''

def get_price_data(self):
response = requests.get(self._url_retail, headers = self._headers)
data = {}
if response.status_code == requests.codes.ok:
data = response.json()
return data['data']
else:
_LOGGER.error('Failed to get price data, %s', response.text)
return data

def get_spot_price(self):
today = datetime.today()
yesterday = today - timedelta(days = 1)
tomorrow = today + timedelta(days = 2)
start = "?from=" + str(yesterday.year) + "-" + yesterday.strftime("%m") + "-" + yesterday.strftime("%d")
end = "&to=" + str(tomorrow.year) + "-" + tomorrow.strftime("%m") + "-" + tomorrow.strftime("%d")
url = self._url_spot_price + self._facility_id + "/spot-price" + start + end + "&resolution=hourly"
response = requests.get(url, headers = self._headers)
data = {}
if response.status_code == requests.codes.ok:
data = response.json()
return data
else:
_LOGGER.error('Failed to get price data, %s', response.text)
return data

def get_usage(self, year, month, day):
url = self._url_data + year + "/" + month + "/" + day + "/usage"
response = requests.get(url, headers = self._headers)
data = {}
if response.status_code == requests.codes.ok:
data = response.json()
return data['data']
else:
_LOGGER.error('Failed to fetch usage data for %s/%s/%s, %s', year, month, day, response.text)
return data

def get_facility_id(self):
result = requests.get(self._url_facilities, headers = self._headers)
if result.status_code == requests.codes.ok:
_LOGGER.debug('jwt is valid!')
data = result.json()
self._facility_id = str(data['data']['parameters']['facility_id'])
else:
_LOGGER.error('Failed to fetch facility id %s', result.text)

def check_auth(self):
"""Check to see if our jwt is valid."""
result = requests.get(self._url_check_auth, headers = self._headers)
if result.status_code == requests.codes.ok:
_LOGGER.debug('jwt is valid!')
return True
else:
if self.login() == False:
_LOGGER.debug(result.text)
return False
return True

def login(self):
"""Login to the Greenely API."""
result = False
loginInfo = {'email':self._email,
'password':self._password}
loginResult = requests.post(self._url_login, headers = self._headers, data = json.dumps(loginInfo))
if loginResult.status_code == requests.codes.ok:
jsonResult = loginResult.json()
self._jwt = "JWT " + jsonResult['jwt']
self._headers['Authorization'] = self._jwt
_LOGGER.debug('Successfully logged in and updated jwt')
self.get_facility_id()
result = True
else:
_LOGGER.error(loginResult.text)
return result
31 changes: 31 additions & 0 deletions custom_components/greenely/const.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
"""Constants for the greenely sensors"""

SENSOR_USAGE_NAME = 'Greenely Usage'
SENSOR_SOLD_NAME = 'Greenely Sold'
SENSOR_PRICES_NAME = 'Greenely Prices'

DOMAIN = 'greenely'

CONF_PRICES = 'prices'
CONF_USAGE = 'usage'
CONF_SOLD = 'sold'
CONF_SOLD_MEASURE = 'sold_measure'
CONF_SOLD_DAILY = 'sold_daily'
CONF_USAGE_DAYS = 'usage_days'
CONF_SHOW_HOURLY = 'show_hourly'
CONF_DATE_FORMAT = 'date_format'
CONF_TIME_FORMAT = 'time_format'
CONF_HOURLY_OFFSET_DAYS = 'hourly_offset_days'

MONITORED_CONDITIONS_DEFAULT = [
'is_retail_customer',
'current_price',
'referral_discount_in_kr',
'has_unpaid_invoices',
'yearly_savings_in_kr',
'timezone',
'retail_termination_date',
'current_day',
'next_day',
'current_month'
]
2 changes: 1 addition & 1 deletion custom_components/greenely/manifest.json
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
{
"domain": "greenely",
"name": "Greenely Sensors",
"version": "1.0.1",
"version": "1.0.2",
"documentation": "https://github.com/linsvensson/sensor.greenely",
"issue_tracker": "https://github.com/linsvensson/sensor.greenely/issues",
"codeowners": ["@linsvensson"],
Expand Down
Loading

0 comments on commit 90d1bb0

Please sign in to comment.