Skip to content

Commit

Permalink
Merge pull request #85 from jontofront/dev
Browse files Browse the repository at this point in the history
Merge branch 'dev' into 'master'
  • Loading branch information
jontofront authored Nov 4, 2024
2 parents 6cea62e + 4023cfc commit 5fbe03a
Show file tree
Hide file tree
Showing 8 changed files with 148 additions and 17 deletions.
12 changes: 12 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -97,4 +97,16 @@ Thank for @pblxptr add new code line from him
- Fixed `ValueError` caused by non-numeric values in sensor state processing.
- Resolved Mypy type incompatibility issue in `STATE_CLASS_MAP` by removing the `servoMixer1` entry with `None` value.

## [v1.0.4-beta] 2024-11-04
#### New Features
- **New Sensors Added**: Introduced new sensors for enhanced monitoring.
- Added sensors: workAt100, workAt50, workAt30, FeederWork, FiringUpCount. (Commit: e41f882)

#### Improvements
- **Valve State Constant**: Changed the valve STATE constant for better consistency. (Commit: 3835797)
- **Entity Value Processor**: Updated ENTITY_VALUE_PROCESSOR to use STATE_ON and STATE_OFF constants for improved state handling. (Commit: 17959c6)
- **Controller Name**: Added 'Controller name' to 'model_id' device info for better support and identification. (Commit: b5cf889)

#### Bug Fixes
- **Boiler Status Keys**: Fixed the mapping of boiler status keys to include operation status. (Commit: a486402)

56 changes: 55 additions & 1 deletion custom_components/econet300/api.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
import logging
from typing import Any

import aiohttp
from aiohttp import BasicAuth, ClientSession
from homeassistant.core import HomeAssistant
from homeassistant.helpers.aiohttp_client import async_get_clientsession
Expand All @@ -15,6 +16,7 @@
API_REG_PARAMS_DATA_PARAM_DATA,
API_REG_PARAMS_DATA_URI,
API_SYS_PARAMS_PARAM_HW_VER,
API_SYS_PARAMS_PARAM_MODEL_ID,
API_SYS_PARAMS_PARAM_SW_REV,
API_SYS_PARAMS_PARAM_UID,
API_SYS_PARAMS_URI,
Expand Down Expand Up @@ -90,6 +92,11 @@ async def set_param(self, key: str, value: str):

async def get_params(self, reg: str):
"""Call for getting api param."""
_LOGGER.debug(
"get_params called: Fetching parameters for registry '%s' from host '%s'",
reg,
self._host,
)
return await self._get(f"{self._host}/econet/{reg}")

async def _get(self, url):
Expand All @@ -98,21 +105,45 @@ async def _get(self, url):

while attempt <= max_attempts:
try:
_LOGGER.debug("Fetching data from URL: %s (Attempt %d)", url, attempt)
_LOGGER.debug(
"Using model_id: %s, sw_revision: %s",
self._model_id,
self._sw_revision,
)
async with await self._session.get(
url, auth=self._auth, timeout=10
) as resp:
_LOGGER.debug("Received response with status: %s", resp.status)
if resp.status == HTTPStatus.UNAUTHORIZED:
_LOGGER.error("Unauthorized access to URL: %s", url)
raise AuthError

if resp.status != HTTPStatus.OK:
try:
error_message = await resp.text()
except (aiohttp.ClientError, aiohttp.ClientResponseError) as e:
error_message = f"Could not retrieve error message: {e}"

_LOGGER.error(
"Failed to fetch data from URL: %s (Status: %s) - Response: %s",
url,
resp.status,
error_message,
)
return None

return await resp.json()
data = await resp.json()
_LOGGER.debug("Fetched data: %s", data)
return data

except TimeoutError:
_LOGGER.warning("Timeout error, retry(%i/%i)", attempt, max_attempts)
await asyncio.sleep(1)
attempt += 1
_LOGGER.error(
"Failed to fetch data from %s after %d attempts", url, max_attempts
)
return None


Expand All @@ -124,9 +155,19 @@ def __init__(self, client: EconetClient, cache: MemCache) -> None:
self._client = client
self._cache = cache
self._uid = "default-uid"
self._model_id = "default-model"
self._sw_revision = "default-sw-revision"
self._hw_version = "default-hw-version"

_LOGGER.debug("Econet300Api initialized with client: %s", client)
_LOGGER.debug("Econet300Api initialized with cache: %s", cache)
_LOGGER.debug("Econet300Api initialized with uid: %s", self._uid)
_LOGGER.debug("Econet300Api initialized with model_id: %s", self._model_id)
_LOGGER.debug(
"Econet300Api initialized with sw_revision: %s", self._sw_revision
)
_LOGGER.debug("Econet300Api initialized with hw_version: %s", self._hw_version)

@classmethod
async def create(cls, client: EconetClient, cache: MemCache):
"""Create and return initial object."""
Expand All @@ -145,6 +186,11 @@ def uid(self) -> str:
"""Get uid."""
return self._uid

@property
def model_id(self) -> str:
"""Get model name."""
return self._model_id

@property
def sw_rev(self) -> str:
"""Get software version."""
Expand All @@ -167,6 +213,14 @@ async def init(self):
else:
self._uid = sys_params[API_SYS_PARAMS_PARAM_UID]

if API_SYS_PARAMS_PARAM_MODEL_ID not in sys_params:
_LOGGER.warning(
"%s not in sys_params - cannot set proper controller model name",
API_SYS_PARAMS_PARAM_MODEL_ID,
)
else:
self._model_id = sys_params[API_SYS_PARAMS_PARAM_MODEL_ID]

if API_SYS_PARAMS_PARAM_SW_REV not in sys_params:
_LOGGER.warning(
"%s not in sys_params - cannot set proper sw_revision",
Expand Down
58 changes: 44 additions & 14 deletions custom_components/econet300/const.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,18 +8,16 @@
SIGNAL_STRENGTH_DECIBELS_MILLIWATT,
STATE_CLOSING,
STATE_OFF,
STATE_ON,
STATE_OPENING,
STATE_PAUSED,
STATE_PROBLEM,
STATE_UNKNOWN,
EntityCategory,
UnitOfTemperature,
UnitOfTime,
)

SERVO_MIXER_VALVE_HA_STATE: dict[int, str] = {
0: STATE_OFF,
1: STATE_CLOSING,
2: STATE_OPENING,
}

# Constant for the econet Integration integration
DOMAIN = "econet300"

Expand All @@ -34,9 +32,16 @@
CONF_ENTRY_TITLE = "ecoNET300"
CONF_ENTRY_DESCRIPTION = "PLUM Econet300"

SERVO_MIXER_VALVE_HA_STATE: dict[int, str] = {
0: STATE_CLOSING,
1: STATE_OFF,
2: STATE_OPENING,
}

## Sys params
API_SYS_PARAMS_URI = "sysParams"
API_SYS_PARAMS_PARAM_UID = "uid"
API_SYS_PARAMS_PARAM_MODEL_ID = "controllerID"
API_SYS_PARAMS_PARAM_SW_REV = "softVer"
API_SYS_PARAMS_PARAM_HW_VER = "routerType"

Expand All @@ -57,16 +62,16 @@
# Boiler staus keys map
# boiler mode names from endpoint http://LocalIP/econet/rmParamsEnums?
OPERATION_MODE_NAMES = {
0: "off",
0: STATE_OFF,
1: "fire_up",
2: "fire_up",
2: "operation",
3: "work",
4: "supervision",
5: "halted",
5: STATE_PAUSED, # "halted",
6: "stop",
7: "burning_off",
8: "manual",
9: "alarm",
9: STATE_PROBLEM, # "alarm",
10: "unsealing",
11: "chimney",
12: "stabilization",
Expand Down Expand Up @@ -112,6 +117,11 @@
"151": "lambdaStatus",
"153": "lambdaSet",
"154": "lambdaLevel",
"155": "workAt100",
"156": "workAt50",
"157": "workAt30",
"158": "FeederWork",
"159": "FiringUpCount",
"168": "main_server",
"170": "signal",
"171": "status_wifi",
Expand Down Expand Up @@ -161,6 +171,11 @@
"tempFeeder": UnitOfTemperature.CELSIUS,
"lambdaLevel": PERCENTAGE,
"lambdaSet": PERCENTAGE,
"workAt100": UnitOfTime.HOURS,
"workAt50": UnitOfTime.HOURS,
"workAt30": UnitOfTime.HOURS,
"FeederWork": UnitOfTime.HOURS,
"FiringUpCount": None,
"thermoTemp": UnitOfTemperature.CELSIUS,
"fanPower": PERCENTAGE,
"tempFlueGas": UnitOfTemperature.CELSIUS,
Expand All @@ -185,6 +200,11 @@
"tempExternalSensor": SensorStateClass.MEASUREMENT,
"lambdaSet": SensorStateClass.MEASUREMENT,
"lambdaLevel": SensorStateClass.MEASUREMENT,
"workAt100": SensorStateClass.MEASUREMENT,
"workAt50": SensorStateClass.MEASUREMENT,
"workAt30": SensorStateClass.MEASUREMENT,
"FeederWork": SensorStateClass.MEASUREMENT,
"FiringUpCount": SensorStateClass.MEASUREMENT,
"tempCO": SensorStateClass.MEASUREMENT,
"tempCOSet": SensorStateClass.MEASUREMENT,
"tempCWUSet": SensorStateClass.MEASUREMENT,
Expand Down Expand Up @@ -295,6 +315,11 @@
"lambdaLevel": "mdi:lambda",
"lambdaSet": "mdi:lambda",
"lambdaStatus": "mdi:lambda",
"workAt100": "mdi:counter",
"workAt50": "mdi:counter",
"workAt30": "mdi:counter",
"FeederWork": "mdi:counter",
"FiringUpCount": "mdi:counter",
"quality": "mdi:signal",
"pumpCOWorks": "mdi:pump",
"fanWorks": "mdi:fan",
Expand All @@ -320,19 +345,19 @@
}

ENTITY_VALUE_PROCESSOR = {
"mode": lambda x: OPERATION_MODE_NAMES.get(x, "unknown"),
"mode": lambda x: OPERATION_MODE_NAMES.get(x, STATE_UNKNOWN),
"thermostat": (
lambda x: (
"ON"
STATE_ON
if str(x).strip() == "true"
else ("OFF" if str(x).strip() == "false" else None)
else (STATE_OFF if str(x).strip() == "false" else None)
)
),
"lambdaStatus": (
lambda x: (
"stop"
if x == 0
else ("start" if x == 1 else ("working" if x == 2 else "unknown"))
else ("start" if x == 1 else ("working" if x == 2 else STATE_UNKNOWN))
)
),
"status_wifi": lambda x: "Connected" if x == 1 else "Disconnected",
Expand All @@ -353,6 +378,11 @@
"controllerID": EntityCategory.DIAGNOSTIC,
"status_wifi": EntityCategory.DIAGNOSTIC,
"main_server": EntityCategory.DIAGNOSTIC,
"workAt100": EntityCategory.DIAGNOSTIC,
"workAt50": EntityCategory.DIAGNOSTIC,
"workAt30": EntityCategory.DIAGNOSTIC,
"FeederWork": EntityCategory.DIAGNOSTIC,
"FiringUpCount": EntityCategory.DIAGNOSTIC,
}

ENTITY_MIN_VALUE = {
Expand Down
3 changes: 3 additions & 0 deletions custom_components/econet300/entity.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
"""Base econet entity class."""

import logging

from homeassistant.core import callback
Expand Down Expand Up @@ -42,6 +43,7 @@ def device_info(self) -> DeviceInfo | None:
name=DEVICE_INFO_CONTROLLER_NAME,
manufacturer=DEVICE_INFO_MANUFACTURER,
model=DEVICE_INFO_MODEL,
model_id=self.api.model_id,
configuration_url=self.api.host,
sw_version=self.api.sw_rev,
hw_version=self.api.hw_ver,
Expand Down Expand Up @@ -115,6 +117,7 @@ def device_info(self) -> DeviceInfo | None:
name=f"{DEVICE_INFO_MIXER_NAME}{self._idx}",
manufacturer=DEVICE_INFO_MANUFACTURER,
model=DEVICE_INFO_MODEL,
model_id=self.api.model_id,
configuration_url=self.api.host,
sw_version=self.api.sw_rev,
via_device=(DOMAIN, self.api.uid),
Expand Down
2 changes: 1 addition & 1 deletion custom_components/econet300/manifest.json
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,6 @@
"issue_tracker": "https://github.com/jontofront/ecoNET-300-Home-Assistant-Integration/issues",
"requirements": [],
"ssdp": [],
"version": "v1.0.3-beta",
"version": "v1.0.4-beta",
"zeroconf": []
}
16 changes: 16 additions & 0 deletions custom_components/econet300/strings.json
Original file line number Diff line number Diff line change
Expand Up @@ -82,6 +82,21 @@
"lambda_level": {
"name": "Lambda level"
},
"work_at100": {
"name": "Work at 100%"
},
"work_at50": {
"name": "Work at 50%"
},
"work_at30": {
"name": "Work at 30%"
},
"feeder_work": {
"name": "Feeder work"
},
"firing_up_count": {
"name": "Firing up count"
},
"main_server": {
"name": "Main server"
},
Expand All @@ -90,6 +105,7 @@
"state": {
"off": "[%key:common::state::off%]",
"fire_up": "Fire up",
"operation": "Operation",
"work": "Work",
"supervision": "Supervision",
"halted": "Halted",
Expand Down
16 changes: 16 additions & 0 deletions custom_components/econet300/translations/en.json
Original file line number Diff line number Diff line change
Expand Up @@ -85,11 +85,27 @@
"main_server": {
"name": "Main server"
},
"work_at100": {
"name": "Work at 100%"
},
"work_at50": {
"name": "Work at 50%"
},
"work_at30": {
"name": "Work at 30%"
},
"feeder_work": {
"name": "Feeder work"
},
"firing_up_count": {
"name": "Firing up count"
},
"mode": {
"name": "Boiler mode",
"state": {
"off": "Off",
"fire_up": "Fire up",
"operation": "Operation",
"work": "Work",
"supervision": "Supervision",
"halted": "Halted",
Expand Down
2 changes: 1 addition & 1 deletion pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

[tool.poetry]
name = "ecoNET-300-Home-Assistant-Integration"
version = "v1.0.3-beta"
version = "v1.0.4-beta"
description = "ecoNET300 Home Assistant integration"
authors = ["Jon <jontofront@gmail.com>"]
readme = "README.md"
Expand Down

0 comments on commit 5fbe03a

Please sign in to comment.