Skip to content

Commit

Permalink
Error messages and logging
Browse files Browse the repository at this point in the history
  • Loading branch information
toreamun committed Jul 11, 2020
1 parent c44c2a3 commit 79debad
Show file tree
Hide file tree
Showing 5 changed files with 104 additions and 119 deletions.
4 changes: 2 additions & 2 deletions .devcontainer/configuration.yaml
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
default_config:

logger:
default: error
default: debug
logs:
custom_components.amshan: debug

ptvsd:
wait: True
#wait: True
56 changes: 27 additions & 29 deletions .devcontainer/devcontainer.json
Original file line number Diff line number Diff line change
@@ -1,31 +1,29 @@
// See https://aka.ms/vscode-remote/devcontainer.json for format details.
{
"image": "ludeeus/container:integration",
"context": "..",
"appPort": [
"9123:8123"
],
"postCreateCommand": "container install",
"runArgs": [
"-v",
"${env:HOME}${env:USERPROFILE}/.ssh:/tmp/.ssh"
],
"extensions": [
"ms-python.python",
"github.vscode-pull-request-github",
"tabnine.tabnine-vscode"
],
"settings": {
"files.eol": "\n",
"editor.tabSize": 4,
"terminal.integrated.shell.linux": "/bin/bash",
"python.pythonPath": "/usr/bin/python3",
"python.linting.pylintEnabled": true,
"python.linting.enabled": true,
"python.formatting.provider": "black",
"editor.formatOnPaste": false,
"editor.formatOnSave": true,
"editor.formatOnType": true,
"files.trimTrailingWhitespace": true
}
}
"image": "ludeeus/container:integration",
"context": "..",
"appPort": ["9123:8123"],
"postCreateCommand": "container install",
"runArgs": ["-v", "${env:HOME}${env:USERPROFILE}/.ssh:/tmp/.ssh"],
"extensions": [
"ms-python.python",
"visualstudioexptteam.vscodeintellicode",
"ms-azure-devops.azure-pipelines",
"redhat.vscode-yaml",
"esbenp.prettier-vscode",
"github.vscode-pull-request-github"
],
"settings": {
"files.eol": "\n",
"editor.tabSize": 4,
"terminal.integrated.shell.linux": "/bin/bash",
"python.pythonPath": "/usr/bin/python3",
"python.linting.pylintEnabled": true,
"python.linting.enabled": true,
"python.formatting.provider": "black",
"editor.formatOnPaste": false,
"editor.formatOnSave": true,
"editor.formatOnType": true,
"files.trimTrailingWhitespace": true
}
}
81 changes: 32 additions & 49 deletions custom_components/amshan/config_flow.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
import socket
import typing
from typing import Any, Dict, Optional
from serial import SerialException

from amshan import autodecoder, obis_map
from homeassistant import config_entries, core, exceptions
Expand Down Expand Up @@ -62,11 +63,16 @@
# Kamstrup sends data frame every 10 sec. Aidon every 2.5 sec. Kaifa evry 2 sec.
MAX_FRAME_WAIT_TIME = 12

# Error codes
# Use the key base if you want to show an error unrelated to a specific field.
# The specified errors need to refer to a key in a translation file.
VALIDATION_ERROR_BASE = "base"
VALIDATION_ERROR_TIMEOUT_CONNECT = "timeout_connect"
VALIDATION_ERROR_TIMEOUT_READ_FRAMES = "timeout_read_frames"
VALIDATION_ERROR_HOST_CHECK = "host_check"
VALIDATION_ERROR_VOLUPTUOUS_BASE = "voluptuous_"
VALIDATION_ERROR_SERIAL_EXCEPTION_GENERAL = "serial_exception_general"
VALIDATION_ERROR_SERIAL_EXCEPTION_ERRNO_2 = "serial_exception_errno_2"


class ConnectionType(Enum):
Expand Down Expand Up @@ -152,56 +158,21 @@ async def async_step_network_connection(
)


# class PlaceholderHub:
# """Placeholder class to make tests pass.

# TODO Remove this placeholder class and replace with things from your PyPI package.
# """

# def __init__(self, host) -> None:
# """Initialize."""
# self.host = host

# async def authenticate(self, username, password) -> bool:
# """Test if we can authenticate with the host."""
# return True


# async def validate_input(hass: core.HomeAssistant, data):
# """
# Validate the user input allows us to connect.

# Data has the keys from DATA_SCHEMA with values provided by the user.
# """
# hub = PlaceholderHub(data["host"])

# if not await hub.authenticate(data["username"], data["password"]):
# raise InvalidAuth

# # If you cannot connect:
# # throw CannotConnect
# # If the authentication is wrong:
# # InvalidAuth

# # Return info that you want to store in the config entry.
# return {"title": "Name of the device"}


# class CannotConnect(exceptions.HomeAssistantError):
# """Error to indicate we cannot connect."""


# class InvalidAuth(exceptions.HomeAssistantError):
# """Error to indicate there is invalid auth."""


class ConfigFlowValidation:
"""ConfigFlow input validation."""

def __init__(self) -> None:
"""Initialize ConfigFlowValidation class."""
self.errors: Dict[str, Any] = {}

def _set_base_error(self, error_key: str) -> None:
"""
Show an error unrelated to a specific field.
:param error_key: error key that needs to refer to a key in a translation file.
"""
self.errors[VALIDATION_ERROR_BASE] = error_key

async def _async_get_meter_info(self, measure_queue: "Queue[bytes]") -> MeterInfo:
"""Decode meter data stream and return meter information if available."""
decoder = autodecoder.AutoDecoder()
Expand All @@ -228,20 +199,32 @@ async def _async_validate_connection(
try:
try:
transport, _ = await connection_factory()
except TimeoutError:
except TimeoutError as ex:
_LOGGER.debug("Timeout when connecting to HAN-port: %s", ex)
self.errors[VALIDATION_ERROR_BASE] = VALIDATION_ERROR_TIMEOUT_CONNECT
self._set_base_error(VALIDATION_ERROR_TIMEOUT_CONNECT)
return None
except SerialException as ex:
if ex.errno == 2:
# No such file or directory
self._set_base_error(VALIDATION_ERROR_SERIAL_EXCEPTION_ERRNO_2)
_LOGGER.debug(
"Serial exception when connecting to HAN-port: %s", ex
)
else:
self._set_base_error(VALIDATION_ERROR_SERIAL_EXCEPTION_GENERAL)
_LOGGER.error(
"Serial exception when connecting to HAN-port: %s", ex
)
return None

except Exception as ex:
_LOGGER.exception("Unexpected error connecting to HAN-port: %s", ex)
raise

try:
return await self._async_get_meter_info(measure_queue)
except TimeoutError:
self.errors[
VALIDATION_ERROR_BASE
] = VALIDATION_ERROR_TIMEOUT_READ_FRAMES
self._set_base_error(VALIDATION_ERROR_TIMEOUT_READ_FRAMES)
return None
finally:
if transport:
Expand All @@ -260,7 +243,7 @@ async def _async_validate_host_address(
flags=0,
)
except OSError:
self.errors["host"] = VALIDATION_ERROR_HOST_CHECK
self.errors[CONF_SERIAL_PORT] = VALIDATION_ERROR_HOST_CHECK

def _validate_schema(
self, connection_type: ConnectionType, user_input: Dict[str, Any]
Expand Down
2 changes: 2 additions & 0 deletions custom_components/amshan/strings.json
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,8 @@
"timeout_connect": "Timeout connecting",
"timeout_read_frames": "Timeout connecting",
"cannot_connect": "Failed to connect, please try again",
"serial_exception_general": "Could not open serial port. See log for details",
"serial_exception_errno_2": "Serial device not found",
"unknown": "Unexpected error"
},
"abort": {
Expand Down
80 changes: 41 additions & 39 deletions custom_components/amshan/translations/en.json
Original file line number Diff line number Diff line change
@@ -1,43 +1,45 @@
{
"config": {
"abort": {
"already_configured": "Device is already configured"
"config": {
"abort": {
"already_configured": "Device is already configured"
},
"error": {
"cannot_connect": "Failed to connect, please try again",
"timeout_connect": "Timeout connecting",
"timeout_read_frames": "Timeout connecting",
"serial_exception_general": "Could not open serial port. See log for details",
"serial_exception_errno_2": "Serial device not found",
"unknown": "Unexpected error",
"voluptuous_host": "Must be a valid hostname or IP-address",
"voluptuous_port": "Must be a valid port number (between 0 and 65353)"
},
"step": {
"network_connection": {
"data": {
"host": "Host address (name or IP)",
"port": "TCP/IP port number"
},
"error": {
"cannot_connect": "Failed to connect, please try again",
"timeout_connect": "Timeout connecting",
"timeout_read_frames": "Timeout connecting",
"unknown": "Unexpected error",
"voluptuous_host": "Must be a valid hostname or IP-address",
"voluptuous_port": "Must be a valid port number (between 0 and 65353)"
"title": "Connect to network host"
},
"serial_connection": {
"data": {
"baudrate": "Baud rate such as 2400, 9600 or 115200 etc.",
"bytesize": "Number of data bits",
"dsrdtr": "Enable hardware (DSR/DTR) flow control",
"parity": "Parity checking",
"port": "Serial device name",
"rtscts": "Enable hardware (RTS/CTS) flow control",
"stopbits": "Number of stop bits",
"xonxoff": "Enable software flow control"
},
"step": {
"network_connection": {
"data": {
"host": "Host address (name or IP)",
"port": "TCP/IP port number"
},
"title": "Connect to network host"
},
"serial_connection": {
"data": {
"baudrate": "Baud rate such as 2400, 9600 or 115200 etc.",
"bytesize": "Number of data bits",
"dsrdtr": "Enable hardware (DSR/DTR) flow control",
"parity": "Parity checking",
"port": "Serial device name",
"rtscts": "Enable hardware (RTS/CTS) flow control",
"stopbits": "Number of stop bits",
"xonxoff": "Enable software flow control"
},
"title": "Connect to serial device"
},
"user": {
"data": {
"type": "Connection type"
},
"title": "Select connection type"
}
}
"title": "Connect to serial device"
},
"user": {
"data": {
"type": "Connection type"
},
"title": "Select connection type"
}
}
}
}
}

0 comments on commit 79debad

Please sign in to comment.