Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Dsmr reader #28701

Merged
merged 12 commits into from
Nov 28, 2019
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
1 change: 1 addition & 0 deletions .coveragerc
Original file line number Diff line number Diff line change
Expand Up @@ -163,6 +163,7 @@ omit =
homeassistant/components/doorbird/*
homeassistant/components/dovado/*
homeassistant/components/downloader/*
homeassistant/components/dsmr_reader/*
homeassistant/components/dte_energy_bridge/sensor.py
homeassistant/components/dublin_bus_transport/sensor.py
homeassistant/components/duke_energy/sensor.py
Expand Down
1 change: 1 addition & 0 deletions CODEOWNERS
Validating CODEOWNERS rules …
Original file line number Diff line number Diff line change
Expand Up @@ -78,6 +78,7 @@ homeassistant/components/device_automation/* @home-assistant/core
homeassistant/components/digital_ocean/* @fabaff
homeassistant/components/discogs/* @thibmaek
homeassistant/components/doorbird/* @oblogic7
homeassistant/components/dsmr_reader/* @depl0y
homeassistant/components/dweet/* @fabaff
homeassistant/components/ecobee/* @marthoc
homeassistant/components/ecovacs/* @OverloadUT
Expand Down
1 change: 1 addition & 0 deletions homeassistant/components/dsmr_reader/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
"""The DSMR Reader component."""
243 changes: 243 additions & 0 deletions homeassistant/components/dsmr_reader/definitions.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,243 @@
"""Definitions for DSMR Reader sensors added to MQTT."""


def dsmr_transform(value):
"""Transform DSMR version value to right format."""
return float(value) / 10


def tariff_transform(value):
"""Transform tariff from number to description."""
if value == "1":
return "low"
return "high"


DEFINITIONS = {
"dsmr/reading/electricity_delivered_1": {
"name": "Low tariff usage",
"icon": "mdi:flash",
"unit": "kWh",
},
"dsmr/reading/electricity_returned_1": {
"name": "Low tariff returned",
"icon": "mdi:flash-outline",
"unit": "kWh",
},
"dsmr/reading/electricity_delivered_2": {
"name": "High tariff usage",
"icon": "mdi:flash",
"unit": "kWh",
},
"dsmr/reading/electricity_returned_2": {
"name": "High tariff returned",
"icon": "mdi:flash-outline",
"unit": "kWh",
},
"dsmr/reading/electricity_currently_delivered": {
"name": "Current power usage",
"icon": "mdi:flash",
"unit": "kW",
},
"dsmr/reading/electricity_currently_returned": {
"name": "Current power return",
"icon": "mdi:flash-outline",
"unit": "kW",
},
"dsmr/reading/phase_currently_delivered_l1": {
"name": "Current power usage L1",
"icon": "mdi:flash",
"unit": "kW",
},
"dsmr/reading/phase_currently_delivered_l2": {
"name": "Current power usage L2",
"icon": "mdi:flash",
"unit": "kW",
},
"dsmr/reading/phase_currently_delivered_l3": {
"name": "Current power usage L3",
"icon": "mdi:flash",
"unit": "kW",
},
"dsmr/reading/phase_currently_returned_l1": {
"name": "Current power return L1",
"icon": "mdi:flash-outline",
"unit": "kW",
},
"dsmr/reading/phase_currently_returned_l2": {
"name": "Current power return L2",
"icon": "mdi:flash-outline",
"unit": "kW",
},
"dsmr/reading/phase_currently_returned_l3": {
"name": "Current power return L3",
"icon": "mdi:flash-outline",
"unit": "kW",
},
"dsmr/reading/extra_device_delivered": {
"name": "Gas meter usage",
"icon": "mdi:fire",
"unit": "m3",
},
"dsmr/reading/phase_voltage_l1": {
"name": "Current voltage L1",
"icon": "mdi:flash",
"unit": "V",
},
"dsmr/reading/phase_voltage_l2": {
"name": "Current voltage L2",
"icon": "mdi:flash",
"unit": "V",
},
"dsmr/reading/phase_voltage_l3": {
"name": "Current voltage L3",
"icon": "mdi:flash",
"unit": "V",
},
"dsmr/consumption/gas/delivered": {
"name": "Gas usage",
"icon": "mdi:fire",
"unit": "m3",
},
"dsmr/consumption/gas/currently_delivered": {
"name": "Current gas usage",
"icon": "mdi:fire",
"unit": "m3",
},
"dsmr/consumption/gas/read_at": {
"name": "Gas meter read",
"icon": "mdi:clock",
"unit": "",
},
"dsmr/day-consumption/electricity1": {
"name": "Low tariff usage",
"icon": "mdi:counter",
"unit": "kWh",
},
"dsmr/day-consumption/electricity2": {
"name": "High tariff usage",
"icon": "mdi:counter",
"unit": "kWh",
},
"dsmr/day-consumption/electricity1_returned": {
"name": "Low tariff return",
"icon": "mdi:counter",
"unit": "kWh",
},
"dsmr/day-consumption/electricity2_returned": {
"name": "High tariff return",
"icon": "mdi:counter",
"unit": "kWh",
},
"dsmr/day-consumption/electricity_merged": {
"name": "Power usage total",
"icon": "mdi:counter",
"unit": "kWh",
},
"dsmr/day-consumption/electricity_returned_merged": {
"name": "Power return total",
"icon": "mdi:counter",
"unit": "kWh",
},
"dsmr/day-consumption/electricity1_cost": {
"name": "Low tariff cost",
"icon": "mdi:currency-eur",
"unit": "€",
},
"dsmr/day-consumption/electricity2_cost": {
"name": "High tariff cost",
"icon": "mdi:currency-eur",
"unit": "€",
},
"dsmr/day-consumption/electricity_cost_merged": {
"name": "Power total cost",
"icon": "mdi:currency-eur",
"unit": "€",
},
"dsmr/day-consumption/gas": {
"name": "Gas usage",
"icon": "mdi:counter",
"unit": "m3",
},
"dsmr/day-consumption/gas_cost": {
"name": "Gas cost",
"icon": "mdi:currency-eur",
"unit": "€",
},
"dsmr/day-consumption/total_cost": {
"name": "Total cost",
"icon": "mdi:currency-eur",
"unit": "€",
},
"dsmr/day-consumption/energy_supplier_price_electricity_delivered_1": {
"name": "Low tariff delivered price",
"icon": "mdi:currency-eur",
"unit": "€",
},
"dsmr/day-consumption/energy_supplier_price_electricity_delivered_2": {
"name": "High tariff delivered price",
"icon": "mdi:currency-eur",
"unit": "€",
},
"dsmr/day-consumption/energy_supplier_price_electricity_returned_1": {
"name": "Low tariff returned price",
"icon": "mdi:currency-eur",
"unit": "€",
},
"dsmr/day-consumption/energy_supplier_price_electricity_returned_2": {
"name": "High tariff returned price",
"icon": "mdi:currency-eur",
"unit": "€",
},
"dsmr/day-consumption/energy_supplier_price_gas": {
"name": "Gas price",
"icon": "mdi:currency-eur",
"unit": "€",
},
"dsmr/meter-stats/dsmr_version": {
"name": "DSMR version",
"icon": "mdi:alert-circle",
"transform": dsmr_transform,
},
"dsmr/meter-stats/electricity_tariff": {
"name": "Electricity tariff",
"icon": "mdi:flash",
"transform": tariff_transform,
},
"dsmr/meter-stats/power_failure_count": {
"name": "Power failure count",
"icon": "mdi:flash",
},
"dsmr/meter-stats/long_power_failure_count": {
"name": "Long power failure count",
"icon": "mdi:flash",
},
"dsmr/meter-stats/voltage_sag_count_l1": {
"name": "Voltage sag L1",
"icon": "mdi:flash",
},
"dsmr/meter-stats/voltage_sag_count_l2": {
"name": "Voltage sag L2",
"icon": "mdi:flash",
},
"dsmr/meter-stats/voltage_sag_count_l3": {
"name": "Voltage sag L3",
"icon": "mdi:flash",
},
"dsmr/meter-stats/voltage_swell_count_l1": {
"name": "Voltage swell L1",
"icon": "mdi:flash",
},
"dsmr/meter-stats/voltage_swell_count_l2": {
"name": "Voltage swell L2",
"icon": "mdi:flash",
},
"dsmr/meter-stats/voltage_swell_count_l3": {
"name": "Voltage swell L3",
"icon": "mdi:flash",
},
"dsmr/meter-stats/rejected_telegrams": {
"name": "Rejected telegrams",
"icon": "mdi:flash",
},
}
12 changes: 12 additions & 0 deletions homeassistant/components/dsmr_reader/manifest.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
{
"domain": "dsmr_reader",
"name": "DSMR Reader",
"documentation": "https://www.home-assistant.io/components/dsmr_reader",
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please replace components with integrations in the url.

"requirements": [],
"dependencies": [
"mqtt"
],
"codeowners": [
"@depl0y"
]
}
87 changes: 87 additions & 0 deletions homeassistant/components/dsmr_reader/sensor.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,87 @@
"""Support for DSMR Reader through MQTT."""
import logging

from homeassistant.components import mqtt
from homeassistant.core import callback
from homeassistant.helpers.entity import Entity
from homeassistant.util import slugify

from .definitions import DEFINITIONS

_LOGGER = logging.getLogger(__name__)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The logger isn't used.


DOMAIN = "dsmr_reader"


async def async_setup_platform(hass, config, async_add_entities, discovery_info=None):
"""Set up DSMR Reader sensors."""

sensors = []
for topic in DEFINITIONS:
sensors.append(DSMRSensor(topic))

async_add_entities(sensors)


class DSMRSensor(Entity):
"""Representation of a DSMR sensor that is updated via MQTT."""

def __init__(self, topic):
"""Initialize the sensor."""

self._definition = DEFINITIONS[topic]

self._entity_id = slugify(topic.replace("/", "_"))
self._topic = topic

self._name = self._definition["name"]
self._unit_of_measurement = (
self._definition["unit"] if "unit" in self._definition else ""
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We can replace the ternary operator with dict.get. It's built for this case.

self._unit_of_measurement = self._definition.get("unit")

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We shouldn't use empty string for unit of measurement. If there's no unit, return None as unit of measurement.

)
self._icon = self._definition["icon"] if "icon" in self._definition else None
self._transform = (
self._definition["transform"] if "transform" in self._definition else None
)

self._state = None

async def async_added_to_hass(self):
"""Subscribe to MQTT events."""

@callback
def message_received(message):
"""Handle new MQTT messages."""

if self._transform is not None:
self._state = self._transform(message.payload)
else:
self._state = message.payload

self.async_schedule_update_ha_state()

return await mqtt.async_subscribe(self.hass, self._topic, message_received, 1)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

async_added_to_hass shouldn't return anything. Please remove the return and just await here.


@property
def name(self):
"""Return the name of the sensor supplied in constructor."""
return self._name

@property
def entity_id(self):
"""Return the entity ID for this sensor."""
return f"sensor.{self._entity_id}"

@property
def state(self):
"""Return the current state of the entity."""
return self._state

@property
def unit_of_measurement(self):
"""Return the unit_of_measurement of this sensor."""
return self._unit_of_measurement

@property
def icon(self):
"""Return the icon of this sensor."""
return self._icon