Compare commits
13 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
a9461e20e6 | ||
|
|
b4c5ceb90e | ||
|
|
9e5ebeb744 | ||
|
|
20502f14ff | ||
|
|
596288161a | ||
|
|
b7b57fb05e | ||
|
|
3edebcf6f8 | ||
|
|
120a717efc | ||
|
|
829f7cbe58 | ||
|
|
e14fb13bcd | ||
|
|
bfaef6ef76 | ||
|
|
b4c756bc40 | ||
|
|
688f9d1088 |
5
.gitignore
vendored
5
.gitignore
vendored
@@ -1 +1,6 @@
|
||||
/build/
|
||||
dist/
|
||||
*.egg-info/
|
||||
__pycache__
|
||||
config.yaml
|
||||
env/
|
||||
8
.travis.yml
Normal file
8
.travis.yml
Normal file
@@ -0,0 +1,8 @@
|
||||
language: python
|
||||
python:
|
||||
- "3.6" # current default Python on Travis CI
|
||||
- "3.7"
|
||||
# command to install dependencies
|
||||
install:
|
||||
- pip install -r requirements.txt
|
||||
# noop change
|
||||
21
CHANGELOG.md
21
CHANGELOG.md
@@ -1,5 +1,26 @@
|
||||
# Changelog
|
||||
|
||||
## v0.5 (2022-05-25)
|
||||
|
||||
Improvements:
|
||||
|
||||
* Support messages containing data for a single meter
|
||||
(electricity or gas only)
|
||||
|
||||
## v0.4 (2021-06-13)
|
||||
|
||||
Improvements:
|
||||
|
||||
* Added grafana dashboard
|
||||
* Added dependencies to setup.py
|
||||
* Published to pypi
|
||||
|
||||
## v0.3 (2020-09-13)
|
||||
|
||||
Misc:
|
||||
|
||||
* Add documentation
|
||||
|
||||
## v0.2 (2020-09-06)
|
||||
|
||||
Bug fixes:
|
||||
|
||||
@@ -40,6 +40,14 @@ docker build -t energy-usage:latest .
|
||||
docker run -v config.yaml:/etc/energy-usage/config.yaml energy-usage:latest
|
||||
```
|
||||
|
||||
## Grafana
|
||||
|
||||
`grafana.energy-usage.json` contains an example Grafana dashboard which consumes this data (using the prometheus query interface of VictoriaMetrics).
|
||||
|
||||

|
||||
|
||||
Upon import of the dashboard, you will be prompted to select your datasource, and enter your unit and standing charges. These are used to plot the costs of realtime usage data, and the daily/weekly/monthly consumption using accumulated usage statistics by the meters. The dashboard does not currently use live tarrif data, as this is not provided in the Bright MQTT feed.
|
||||
|
||||
## Tested with:
|
||||
|
||||
* Python 3
|
||||
|
||||
BIN
energy-usage-dashboard.png
Normal file
BIN
energy-usage-dashboard.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 201 KiB |
@@ -1 +1 @@
|
||||
VERSION = "0.1"
|
||||
VERSION = "0.5"
|
||||
|
||||
@@ -99,6 +99,7 @@ def main():
|
||||
usage = parse_sep(msg.topic, msg.payload)
|
||||
if usage:
|
||||
usage_datapoints = usage_to_datapoints(usage)
|
||||
logger.debug('Writing metrics to influx: %s', usage_datapoints)
|
||||
if not config["noop"].get(bool):
|
||||
influx_client.write_points(usage_datapoints)
|
||||
except KeyboardInterrupt:
|
||||
|
||||
@@ -31,30 +31,7 @@ def parse_sep(topic, payload_str):
|
||||
|
||||
payload = json.loads(payload_str)
|
||||
|
||||
try:
|
||||
assert(_get_metric(["elecMtr", "0702", "03", "00"]) == 0) # kWh
|
||||
assert(_get_metric(["gasMtr", "0702", "03", "01"]) == 1) # m3
|
||||
assert(_get_metric(["gasMtr", "0702", "03", "12"]) == 0) # kWh
|
||||
except AssertionError:
|
||||
logger.warning("Received a payload without expected data")
|
||||
return None
|
||||
|
||||
timestamp = datetime.datetime.fromtimestamp(payload["gmtime"], tz=datetime.timezone.utc)
|
||||
electricity_consumption = _get_metric(["elecMtr", "0702", "04", "00"])
|
||||
electricity_daily_consumption = _get_metric(["elecMtr", "0702", "04", "01"])
|
||||
electricity_weekly_consumption = _get_metric(["elecMtr", "0702", "04", "30"])
|
||||
electricity_monthly_consumption = _get_metric(["elecMtr", "0702", "04", "40"])
|
||||
electricity_multiplier = _get_metric(["elecMtr", "0702", "03", "01"])
|
||||
electricity_divisor = _get_metric(["elecMtr", "0702", "03", "02"])
|
||||
electricity_meter = _get_metric(["elecMtr", "0702", "00", "00"])
|
||||
electricity_mpan = _get_metric(["elecMtr", "0702", "03", "07"], str)
|
||||
gas_daily_consumption = _get_metric(["gasMtr", "0702", "0C", "01"])
|
||||
gas_weekly_consumption = _get_metric(["gasMtr", "0702", "0C", "30"])
|
||||
gas_monthly_consumption = _get_metric(["gasMtr", "0702", "0C", "40"])
|
||||
gas_multiplier = _get_metric(["gasMtr", "0702", "03", "01"])
|
||||
gas_divisor = _get_metric(["gasMtr", "0702", "03", "02"])
|
||||
gas_meter = _get_metric(["gasMtr", "0702", "00", "00"])
|
||||
gas_mpan = _get_metric(["gasMtr", "0702", "03", "07"], str)
|
||||
device_gid = _get_metric(["gid"], str)
|
||||
|
||||
data = {
|
||||
@@ -63,7 +40,21 @@ def parse_sep(topic, payload_str):
|
||||
'topic': topic,
|
||||
'gid': device_gid,
|
||||
},
|
||||
'electricity': {
|
||||
}
|
||||
|
||||
try:
|
||||
assert(_get_metric(["elecMtr", "0702", "03", "00"]) == 0) # kWh
|
||||
|
||||
electricity_consumption = _get_metric(["elecMtr", "0702", "04", "00"])
|
||||
electricity_daily_consumption = _get_metric(["elecMtr", "0702", "04", "01"])
|
||||
electricity_weekly_consumption = _get_metric(["elecMtr", "0702", "04", "30"])
|
||||
electricity_monthly_consumption = _get_metric(["elecMtr", "0702", "04", "40"])
|
||||
electricity_multiplier = _get_metric(["elecMtr", "0702", "03", "01"])
|
||||
electricity_divisor = _get_metric(["elecMtr", "0702", "03", "02"])
|
||||
electricity_meter = _get_metric(["elecMtr", "0702", "00", "00"])
|
||||
electricity_mpan = _get_metric(["elecMtr", "0702", "03", "07"], str)
|
||||
|
||||
data.update({'electricity': {
|
||||
'tags': {
|
||||
'mpan': electricity_mpan,
|
||||
},
|
||||
@@ -74,8 +65,23 @@ def parse_sep(topic, payload_str):
|
||||
'consumption_monthly': electricity_monthly_consumption * electricity_multiplier / electricity_divisor,
|
||||
'meter_reading': electricity_meter * electricity_multiplier / electricity_divisor,
|
||||
},
|
||||
},
|
||||
'gas': {
|
||||
}})
|
||||
except AssertionError:
|
||||
pass
|
||||
|
||||
try:
|
||||
assert(_get_metric(["gasMtr", "0702", "03", "01"]) == 1) # m3
|
||||
assert(_get_metric(["gasMtr", "0702", "03", "12"]) == 0) # kWh
|
||||
|
||||
gas_daily_consumption = _get_metric(["gasMtr", "0702", "0C", "01"])
|
||||
gas_weekly_consumption = _get_metric(["gasMtr", "0702", "0C", "30"])
|
||||
gas_monthly_consumption = _get_metric(["gasMtr", "0702", "0C", "40"])
|
||||
gas_multiplier = _get_metric(["gasMtr", "0702", "03", "01"])
|
||||
gas_divisor = _get_metric(["gasMtr", "0702", "03", "02"])
|
||||
gas_meter = _get_metric(["gasMtr", "0702", "00", "00"])
|
||||
gas_mpan = _get_metric(["gasMtr", "0702", "03", "07"], str)
|
||||
|
||||
data.update({'gas': {
|
||||
'tags': {
|
||||
'mpan': gas_mpan,
|
||||
},
|
||||
@@ -85,8 +91,13 @@ def parse_sep(topic, payload_str):
|
||||
'consumption_monthly': gas_monthly_consumption * gas_multiplier / gas_divisor,
|
||||
'meter_reading': gas_meter * gas_multiplier / gas_divisor,
|
||||
},
|
||||
},
|
||||
}
|
||||
}})
|
||||
except AssertionError:
|
||||
pass
|
||||
|
||||
if 'electricity' not in data and 'gas' not in data:
|
||||
logger.warning("Received a payload without either electricity or gas data")
|
||||
return None
|
||||
|
||||
return data
|
||||
|
||||
@@ -95,11 +106,12 @@ def usage_to_datapoints(usage):
|
||||
datapoints = []
|
||||
|
||||
for utility in ['electricity', 'gas']:
|
||||
datapoints.append({
|
||||
"measurement": utility,
|
||||
"tags": {**usage['tags'], **usage[utility]['tags']},
|
||||
"time": usage['timestamp'].isoformat(),
|
||||
"fields": usage[utility]['metrics'],
|
||||
})
|
||||
if utility in usage:
|
||||
datapoints.append({
|
||||
"measurement": utility,
|
||||
"tags": {**usage['tags'], **usage[utility]['tags']},
|
||||
"time": usage['timestamp'].isoformat(),
|
||||
"fields": usage[utility]['metrics'],
|
||||
})
|
||||
|
||||
return datapoints
|
||||
|
||||
1654
grafana.energy-usage.json
Normal file
1654
grafana.energy-usage.json
Normal file
File diff suppressed because it is too large
Load Diff
Reference in New Issue
Block a user