Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 4 additions & 5 deletions custom_components/goecharger_mqtt/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@

from .const import (
ATTR_KEY,
ATTR_SERIAL_NUMBER,
ATTR_TOPIC,
ATTR_VALUE,
DEFAULT_TOPIC_PREFIX,
DOMAIN,
Expand All @@ -31,7 +31,7 @@

SERVICE_SCHEMA_SET_CONFIG_KEY = vol.Schema(
{
vol.Required(ATTR_SERIAL_NUMBER): cv.string,
vol.Required(ATTR_TOPIC): cv.string,
vol.Required(ATTR_KEY): cv.string,
vol.Required(ATTR_VALUE): cv.string,
}
Expand All @@ -58,10 +58,9 @@ async def async_setup(hass: HomeAssistant, config: ConfigType) -> bool:

@callback
async def set_config_key_service(call: ServiceCall) -> None:
serial_number = call.data.get("serial_number")
topic = call.data.get(ATTR_TOPIC)
key = call.data.get("key")
# @FIXME: Retrieve the topic_prefix from config_entry
topic = f"{DEFAULT_TOPIC_PREFIX}/{serial_number}/{key}/set"
topic = f"{topic}/{key}/set"
value = call.data.get("value")

if not value.isnumeric():
Expand Down
37 changes: 15 additions & 22 deletions custom_components/goecharger_mqtt/config_flow.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,13 +5,14 @@
from typing import Any

from homeassistant import config_entries
from homeassistant.components import mqtt
from homeassistant.core import HomeAssistant
from homeassistant.data_entry_flow import FlowResult
from homeassistant.exceptions import HomeAssistantError
from homeassistant.helpers import config_validation as cv
import voluptuous as vol

from .const import CONF_SERIAL_NUMBER, CONF_TOPIC_PREFIX, DEFAULT_TOPIC_PREFIX, DOMAIN
from .const import CONF_TOPIC, DEFAULT_TOPIC_PREFIX, DOMAIN

try:
# < HA 2022.8.0
Expand All @@ -26,8 +27,7 @@

STEP_USER_DATA_SCHEMA = vol.Schema(
{
vol.Required(CONF_SERIAL_NUMBER): vol.All(cv.string, vol.Length(min=6, max=6)),
vol.Required(CONF_TOPIC_PREFIX, default=DEFAULT_TOPIC_PREFIX): cv.string,
vol.Required(CONF_TOPIC, default=DEFAULT_TOPIC_PREFIX): cv.string,
}
)

Expand All @@ -38,10 +38,9 @@ class PlaceholderHub:
TODO Remove this placeholder class and replace with things from your PyPI package.
"""

def __init__(self, topic_prefix: str, serial_number: str) -> None:
def __init__(self, topic: str) -> None:
"""Initialize."""
self.topic_prefix = topic_prefix
self.serial_number = serial_number
self.topic = topic

async def validate_device_topic(self) -> bool:
"""Test if we can authenticate with the host."""
Expand All @@ -53,13 +52,15 @@ async def validate_input(hass: HomeAssistant, data: dict[str, Any]) -> dict[str,

Data has the keys from STEP_USER_DATA_SCHEMA with values provided by the user.
"""
serial_number = data[CONF_SERIAL_NUMBER]
hub = PlaceholderHub(data[CONF_TOPIC_PREFIX], serial_number)
topic = data[CONF_TOPIC]
hub = PlaceholderHub(topic)

if not await hub.validate_device_topic():
raise CannotConnect

return {"title": f"{DEFAULT_NAME} {serial_number}"}
device_name = topic.split("/")[-1]

return {"title": f"{DEFAULT_NAME} {device_name}"}


class ConfigFlow(config_entries.ConfigFlow, domain=DOMAIN):
Expand All @@ -69,8 +70,7 @@ class ConfigFlow(config_entries.ConfigFlow, domain=DOMAIN):

def __init__(self) -> None:
"""Initialize flow."""
self._serial_number = None
self._topic_prefix = None
self._topic = None

async def async_step_mqtt(self, discovery_info: MqttServiceInfo) -> FlowResult:
"""Handle a flow initialized by MQTT discovery."""
Expand All @@ -80,15 +80,9 @@ async def async_step_mqtt(self, discovery_info: MqttServiceInfo) -> FlowResult:
assert subscribed_topic in ["/go-eCharger/+/var", "go-eCharger/+/var"]

# Example topic: /go-eCharger/072246/var
topic = discovery_info.topic
(prefix, suffix) = subscribed_topic.split("+", 2)
self._serial_number = topic.replace(prefix, "").replace(suffix, "")
self._topic_prefix = prefix[:-1]

if not self._serial_number.isnumeric():
return self.async_abort(reason="invalid_discovery_info")
self._topic = discovery_info.topic.replace("/var", "")

await self.async_set_unique_id(self._serial_number)
await self.async_set_unique_id(self._topic)
self._abort_if_unique_id_configured()

return await self.async_step_discovery_confirm()
Expand All @@ -104,8 +98,7 @@ async def async_step_discovery_confirm(
return self.async_create_entry(
title=name,
data={
CONF_SERIAL_NUMBER: self._serial_number,
CONF_TOPIC_PREFIX: self._topic_prefix,
CONF_TOPIC: self._topic,
},
)

Expand Down Expand Up @@ -136,7 +129,7 @@ async def async_step_user(
_LOGGER.exception("Unexpected exception")
errors["base"] = "unknown"
else:
await self.async_set_unique_id(user_input[CONF_SERIAL_NUMBER])
await self.async_set_unique_id(user_input[CONF_TOPIC])
self._abort_if_unique_id_configured()

return self.async_create_entry(title=info["title"], data=user_input)
Expand Down
7 changes: 3 additions & 4 deletions custom_components/goecharger_mqtt/const.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,14 +2,13 @@

DOMAIN = "goecharger_mqtt"

ATTR_SERIAL_NUMBER = "serial_number"
ATTR_TOPIC = "serial_number"
ATTR_KEY = "key"
ATTR_VALUE = "value"

CONF_SERIAL_NUMBER = "serial_number"
CONF_TOPIC_PREFIX = "topic_prefix"
CONF_TOPIC = "topic"

DEFAULT_TOPIC_PREFIX = "/go-eCharger"
DEFAULT_TOPIC_PREFIX = "go-eCharger/"

DEVICE_INFO_MANUFACTURER = "go-e"
DEVICE_INFO_MODEL = "go-eCharger HOME"
12 changes: 5 additions & 7 deletions custom_components/goecharger_mqtt/entity.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,7 @@
from homeassistant.util import slugify

from .const import (
CONF_SERIAL_NUMBER,
CONF_TOPIC_PREFIX,
CONF_TOPIC,
DEVICE_INFO_MANUFACTURER,
DEVICE_INFO_MODEL,
DOMAIN,
Expand All @@ -22,19 +21,18 @@ def __init__(
description: GoEChargerEntityDescription,
) -> None:
"""Initialize the sensor."""
topic_prefix = config_entry.data[CONF_TOPIC_PREFIX]
serial_number = config_entry.data[CONF_SERIAL_NUMBER]
topic = config_entry.data[CONF_TOPIC]

self._topic = f"{topic_prefix}/{serial_number}/{description.key}"
self._topic = f"{topic}/{description.key}"

slug = slugify(self._topic.replace("/", "_"))
self.entity_id = f"{description.domain}.{slug}"

self._attr_unique_id = "-".join(
[serial_number, description.domain, description.key, description.attribute]
[topic, description.domain, description.key, description.attribute]
)
self._attr_device_info = DeviceInfo(
identifiers={(DOMAIN, serial_number)},
identifiers={(DOMAIN, topic)},
name=config_entry.title,
manufacturer=DEVICE_INFO_MANUFACTURER,
model=DEVICE_INFO_MODEL,
Expand Down
5 changes: 2 additions & 3 deletions custom_components/goecharger_mqtt/strings.json
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,7 @@
"user": {
"description": "[%key:common::config_flow::description%]",
"data": {
"serial_number": "[%key:common::config_flow::data::serial_number%]",
"topic_prefix": "[%key:common::config_flow::data::topic_prefix%]"
"topic": "[%key:common::config_flow::data::topic%]"
}
}
},
Expand All @@ -22,4 +21,4 @@
"already_configured": "[%key:common::config_flow::abort::already_configured_device%]"
}
}
}
}
7 changes: 3 additions & 4 deletions custom_components/goecharger_mqtt/translations/en.json
Original file line number Diff line number Diff line change
Expand Up @@ -14,12 +14,11 @@
"description": "Do you want to setup {name}?"
},
"user": {
"description": "Please provide the serial number of your device",
"description": "Please provide the MQTT topic of your device",
"data": {
"serial_number": "Serial number",
"topic_prefix": "Base topic"
"topic": "MQTT topic"
}
}
}
}
}
}
8 changes: 3 additions & 5 deletions tests/test_config_flow.py
Original file line number Diff line number Diff line change
Expand Up @@ -25,15 +25,13 @@ async def test_form(hass: HomeAssistant) -> None:
) as mock_setup_entry:
result2 = await hass.config_entries.flow.async_configure(
result["flow_id"],
{"serial_number": "012345", "topic_prefix": "/go-eCharger"},
{"topic": "/go-eCharger/012345"},
)
await hass.async_block_till_done()

assert result2["type"] == RESULT_TYPE_CREATE_ENTRY
assert result2["title"] == "go-eCharger 012345"
assert result2["data"] == {
"serial_number": "012345",
"topic_prefix": "/go-eCharger",
assert result2["data"] == {"topic": "/go-eCharger/012345"
}
assert len(mock_setup_entry.mock_calls) == 1

Expand All @@ -50,7 +48,7 @@ async def test_form_cannot_connect(hass: HomeAssistant) -> None:
):
result2 = await hass.config_entries.flow.async_configure(
result["flow_id"],
{"serial_number": "012345", "topic_prefix": "/go-eCharger"},
{"topic": "/go-eCharger/012345"},
)

assert result2["type"] == RESULT_TYPE_FORM
Expand Down