Skip to content

Commit

Permalink
Merge pull request #16 from djw4/main
Browse files Browse the repository at this point in the history
Swap to env for configuration
  • Loading branch information
proffalken authored Nov 18, 2021
2 parents eb45214 + de745de commit bbdce48
Show file tree
Hide file tree
Showing 6 changed files with 127 additions and 23 deletions.
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -137,3 +137,4 @@ dmypy.json
# Cython debug symbols
cython_debug/

Pipfile.lock
26 changes: 26 additions & 0 deletions Pipfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
[[source]]
url = "https://pypi.org/simple"
verify_ssl = true
name = "pypi"

[packages]
certifi = "==2020.12.5"
chardet = "==4.0.0"
click = "==7.1.2"
gunicorn = "==20.0.4"
idna = "==2.10"
itsdangerous = "==1.1.0"
requests = "==2.25.1"
urllib3 = "==1.26.5"
Flask = "==1.1.2"
Jinja2 = "==2.11.3"
MarkupSafe = "==1.1.1"
Werkzeug = "==1.0.1"

[dev-packages]

[requires]
python_version = "3.9"

[scripts]
app = "gunicorn -w 4 -b 0.0.0.0:5000 app:app"
78 changes: 69 additions & 9 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -11,28 +11,70 @@ and returns the metrics in a format suitable for consumption by

This is the recommended way to launch the service as it takes care of the dependencies for you.

First, update the `config/hubitat2prom.yml` file with the URL and access token for your MakerAPI. This can be found
in the MakerAPI settings on your Hubitat device.
First, retrieve your API token and API path from your Hubitat device. These will look something like;

- HE_URI: `http://<hubitat_hostname>/apps/api/26/devices`
- HE_TOKEN: `f4a20ab3-..-670f559be5a6`

Put these values into a new file named `.env` as below:

```
HE_URI=http://<hubitat_hostname>/apps/api/26/devices
HE_TOKEN=f4a20ab3-..-670f559be5a6
```

Next, run the following command to start the container:

`docker run --privileged -v "$(pwd)"/config:/app/config -p 5000:5000 ghcr.io/budgetsmarthome/hubitat2prom:sha-dba43ca`
```bash
docker run --rm --env-file .env -p 5000:5000 ghcr.io/budgetsmarthome/hubitat2prom:latest
```

You can also use docker-compose if you prefer:

```bash
$ cat <<EOF >docker-compose.yaml
---
version: '3'
services:
hubitat2prom:
image: ghcr.io/budgetsmarthome/hubitat2prom:latest
env_file:
- '.env'
ports:
- 5000:5000
EOF

$ docker-compose run --rm hubitat2prom
```

This will start the container listening on your local machine on port 5000, and you can visit
[http://localhost:5000/metrics](http://localhost:5000/metrics) to confirm that the metrics are coming through.

You can additionally visit
[http://localhost:5000/info](http://localhost:5000/info) to view basic
configuration infomation and check the connection status with the Hubitat API.

Once you've confirmed this, you can move on to configuring Prometheus.

## Local Installation

If you want to run this service without installing from Docker, then the steps are as follows:
If you want to run this service without installing from Docker, then the steps
are as follows:

1. Install `pipenv` for python3; `python3 -m pip install pipenv`.
2. Create the `.env` file as per the instructions above.
3. Run the following command: `pipenv run app`

1. Configure `config/hubitat2prom.yml` as documented in the `Docker` section of this readme.
2. Install the requirements from `requirements.txt` into an appropriate virtual environment
3. Run the following command: `export FLASK_APP=app;export HEPROM_CFG_FILE="path/to/config/file" && flask run`
A Python virtual environment will be created automatically, if the service has
never run before and then pipenv will also automatically install all of the
dependencies that the service requires to run. After this is completed the
application will start. If you stop and start the application, the dependencies
will persist unless otherwise removed.

As with the docker container, your service will now be exposed on port 5000, and you can test it is working
by visiting [http://localhost:5000/metrics](http://localhost:5000/metrics) in a browser.
As with the docker container, your service will now be exposed on port 5000, and
you can test it is working by visiting
[http://localhost:5000/metrics](http://localhost:5000/metrics) in a browser.

## Prometheus

Expand All @@ -49,6 +91,24 @@ Add the following to the bottom of your Prometheus Outputs:

Prometheus will now scrape your web service every 30 seconds to update the metrics in the data store.

## InfluxDB

Configuring InfluxDB is equally as simple.

Visit the InfluxDB admin console, then navigate to;
`Data --> Scrapers --> 'Create Scraper'`

Provide a name to your scraper, assign a bucket where the data should be stored,
then provide the path to the metrics path as listed above, substituting your
localhost address with the IP address/hostname of the server running the
container.

![InfluxDB - Create Scraper](/screenshots/influxdb-scraper.jpg)

Metrics data from your new scraper is now available to be queried:

![InfluxDB - Query Metrics](/screenshots/influxdb-query.jpg)

# Collected Metrics

Hubitat2Prom is capable of collecting any of the metrics that Hubitat exposes via the MakerAPI.
Expand Down
45 changes: 31 additions & 14 deletions app.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,29 +2,46 @@
import os
import requests
import time
import yaml

from flask import render_template, Flask, make_response
from flask import render_template, Flask, make_response, Response

app = Flask(__name__)

# Load the config file
config_file = os.getenv("HE2PROM_CFG_FILE") or "/app/config/hubitat2prom.yml"
with open(config_file, "r") as configfile:
config = yaml.load(
configfile,
Loader=yaml.SafeLoader)
# Load the configuration values from environment variables - HE_URI and HE_TOKEN
# are mandatory, however a default collection of metrics is provided if the
# HE_METRICS env is missing.
try:
base_uri = os.environ["HE_URI"]
access_token = os.environ["HE_TOKEN"]
collected_metrics = os.getenv("HE_METRICS", "battery,humidity,illuminance,level,switch,temperature,power,energy").split(",")
except KeyError as e:
print(f"Could not read the environment variable - {e}")

base_uri = config["hubitat"]["base_uri"]
access_token = config["hubitat"]["access_token"]
def get_devices():
return requests.get(f"{base_uri}?access_token={access_token}")

# This is the default set of metrics to be collected
collected_metrics = config['collected_metrics']
@app.route("/info")
def info():
res = {
"status": {
"CONNECTION": "ONLINE" if get_devices().status_code == 200 else "OFFLINE"
},
"config": {
"HE_URI": base_uri,
"HE_TOKEN": access_token,
"HE_METRICS": collected_metrics
}
}
response = app.response_class(
response=json.dumps(res),
status=200,
mimetype='application/json'
)
return response

@app.route("/metrics")
def metrics():
devices = requests.get(f"{base_uri}?access_token={access_token}")

devices = get_devices()
device_attributes = []

for device in devices.json():
Expand Down
Binary file added screenshots/influxdb-query.jpg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added screenshots/influxdb-scraper.jpg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.

0 comments on commit bbdce48

Please sign in to comment.