Config Flow label/comment issue

Hi,

I’m having a problem with labels in a config flow of a custom component I’m preparing. I looked at all relevant threads about strings.json, en.json, browser cache issues, etc. but I didn’t solve.

Here’s the repo: alexdelprete/ha-abb-powerone-pvi-sunspec: Home assistant Custom Component to integrate data from ABB/Power-One/FIMER PV 3-phase Inverters with support for SunSpec Modbus TCP (Sunspec M103 and M160), natively or through the VSN300 wifi logger card. (github.com)

This is the config dialog box: the problem is with the 3rd field, which has a default value of 2, the field name is slave_id. The label/comment for that field does not appear. It’s not the browser cache, and if I update some labels in en.json the updates are actually being picked up. It’s like the “slave_id” field is not found in some way. The problem is only the label/comment, if I submit the values the component works fine.

image

This is the content of en.json under the translations subdir:

{
  "config": {
    "title": "ABB Power-One PVI SunSpec",
    "step": {
      "user": {
        "title": "Inverter Connection Configuration",
        "data": {
          "name": "Assign name to the inverter (used as sensors' prefix)",
          "host": "IP address of the inverter",
          "port": "TCP port of the inverter",
          "slave_id": "Modbus Slave ID of the inverter",
          "scan_interval": "Polling period for the modbus registers (seconds)"
        }
      }
    },
    "error": {
      "already_configured": "Device is already configured"
    },
    "abort": {
      "already_configured": "Device is already configured"
    }
  }
}

This is the content of config_flow.py:

import ipaddress
import re

import voluptuous as vol

from homeassistant.core import HomeAssistant, callback
from homeassistant import config_entries
from homeassistant.const import CONF_NAME, CONF_HOST, CONF_PORT, CONF_SCAN_INTERVAL
from .const import (
    DOMAIN,
    DEFAULT_NAME,
    DEFAULT_PORT,
    CONF_SLAVE_ID,
    DEFAULT_SLAVE_ID,
    DEFAULT_SCAN_INTERVAL,
)

DATA_SCHEMA = vol.Schema(
    {
        vol.Required(CONF_NAME, default=DEFAULT_NAME): str,
        vol.Required(CONF_HOST): str,
        vol.Required(CONF_PORT, default=DEFAULT_PORT): int,
        vol.Required(CONF_SLAVE_ID, default=DEFAULT_SLAVE_ID): int,
        vol.Optional(CONF_SCAN_INTERVAL, default=DEFAULT_SCAN_INTERVAL): int,
    }
)


def host_valid(host):
    """Return True if hostname or IP address is valid."""
    try:
        if ipaddress.ip_address(host).version == (4 or 6):
            return True
    except ValueError:
        disallowed = re.compile(r"[^a-zA-Z\d\-]")
        return all(x and not disallowed.search(x) for x in host.split("."))


@callback
def abb_powerone_pvi_sunspec_entries(hass: HomeAssistant):
    """Return the hosts already configured."""
    return set(
        entry.data[CONF_HOST] for entry in hass.config_entries.async_entries(DOMAIN)
    )


class ABBPowerOnePVISunSpecConfigFlow(config_entries.ConfigFlow, domain=DOMAIN):
    """ABB Power-One PVI SunSpec configflow"""

    VERSION = 1
    CONNECTION_CLASS = config_entries.CONN_CLASS_LOCAL_POLL

    def _host_in_configuration_exists(self, host) -> bool:
        """Return True if host exists in configuration."""
        if host in abb_powerone_pvi_sunspec_entries(self.hass):
            return True
        return False

    async def async_step_user(self, user_input=None):
        """Handle the initial step."""
        errors = {}

        if user_input is not None:
            host = user_input[CONF_HOST]

            if self._host_in_configuration_exists(host):
                errors[CONF_HOST] = "already_configured"
            elif not host_valid(user_input[CONF_HOST]):
                errors[CONF_HOST] = "invalid host IP"
            else:
                await self.async_set_unique_id(user_input[CONF_HOST])
                self._abort_if_unique_id_configured()
                return self.async_create_entry(
                    title=user_input[CONF_NAME], data=user_input
                )

        return self.async_show_form(
            step_id="user", data_schema=DATA_SCHEMA, errors=errors
        )

Any help would be greatly appreciated, I want to release the component, but I have to fix this last issue first.

Thank you.

I think the problem is that “slave_id” in en.json must match your CONF_SLAVE_ID in your const.py, so in your const.py do:
CONF_SLAVE_ID="slave_id"

1 Like

Should have asked you 4 hours ago…I was getting crazy. Now I think I understand how it works. Documentations is not very clear unfortunately.

image

Thank you so much Johan. :slight_smile:

You’re welcome, glad i could help :slight_smile:

1 Like