Skip to content

Commit

Permalink
Merge pull request #66 from maorcc/refactor-component
Browse files Browse the repository at this point in the history
Refactor component
  • Loading branch information
elad-bar authored May 31, 2024
2 parents dfeda0f + 5926982 commit 7b3b1a6
Show file tree
Hide file tree
Showing 84 changed files with 3,641 additions and 4,148 deletions.
27 changes: 27 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,32 @@
# Changelog

## v3.0.0

**Breaking Changes:**

- Device & Entity names changed
- Meter device name is now constructed by meter's address and serial number
- Account device name is now constructed by owner's first & last Name and account number
- Alert settings dropdown are now being represented as:
- Alert leak via Email - binary sensor
- Others - switch

**What's Changed:**

- Refactor integration
- Isolated API logic, data processing and HA functionality
- Add tool to translate component to additional languages automatically using Google Translate
- Fully translated to Hebrew
- Extend diagnostic file to support all data collected from API and internal state data
- Move cost configuration into meter device (per meter) using number entities
- Low Rate Cost - Default 7.955 ILS/m³
- High Rate Cost - Default 14.6 ILS/m³
- Low Rate Cost - Default 7.955 ILS/m³
- Sewage Cost - Default 0 ILS/m³
- Low Rate Consumption Threshold - Default 3.5 m³ (Equivalent to 7m³ per 2 months of 1 person in property)

_Default values taken from [gov.il](https://www.gov.il/he/pages/rates_general1) and up to date to January 1st 2024_

## v2.0.15

- Use https://eu-customerportal-api.harmonyencoremdm.com as the new api url
Expand Down
136 changes: 39 additions & 97 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -64,124 +64,66 @@ _Configuration -> Integrations -> {Integration} -> Options_ <br />
| Email | Textbox | + | - | Email registered to City Mind v2 |
| Password | Textbox | + | - | Password of the account registered to City Mind v2 |

#### Debugging

**Logging**

To set the log level of the component to DEBUG, please set it from the options of the component if installed, otherwise, set it within configuration YAML of HA:

```yaml
logger:
default: warning
logs:
custom_components.citymind_water_meter: debug
```
**Debug files**
Integration support store debug files which saves the data provided by `Read Your Meter Pro` to:

`/config/.storage/citymind_water_meter.{entry_id}.debug.api.json`

## Components

### Account

| Entity Name | Type | Description | Additional information |
| ------------------------------------------------------ | ------ | ------------------------------------------------------------------------------------------------------------------- | -------------------------------------------- |
| CityMind {Account ID} Account Alert Exceeded threshold | Select | Allows to control which communication channel should receive an alert when daily consumption exceeded threshold | Available options are: None, Email, SMS, All |
| CityMind {Account ID} Account Alert Leak | Select | Allows to control which communication channel should receive an alert when leak identified | Available options are: None, Email, SMS, All |
| CityMind {Account ID} Account Alert Leak While Away | Select | Allows to control which communication channel should receive an alert when leak identified when vacation is defined | Available options are: None, Email, SMS, All |
| CityMind {Account ID} Account Alerts | Sensor | Indicates number of alerts set in the portal | Attributes holds the alerts list |
| CityMind {Account ID} Account Messages | Sensor | Indicates number of messages set in the portal | Attributes holds the messages list |
| CityMind {Account ID} Account Vacations | Sensor | Indicates number of vacations set in the portal | Attributes holds the vacations list |
| Entity Name | Type | Description | Additional information |
| ------------------------------------------------------------------ | ------------- | ------------------------------------------------------------------------------------------ | -------------------------------- |
| {Owner} {Account ID} Alerts | Sensor | Indicates number of alerts set in the portal | Attributes holds the alerts list |
| {Owner} {Account ID} Consumption Alert Leak (Email) | Binary Sensor | Allows to control which communication channel should receive an alert when leak identified | |
| {Owner} {Account ID} Consumption Alert Leak (SMS) | Switch | Allows to control which communication channel should receive an alert when leak identified | |
| {Owner} {Account ID} Consumption Alert While Away (Email) | Switch | Allows to control which communication channel should receive an alert when leak identified | |
| {Owner} {Account ID} Consumption Alert While Away (SMS) | Switch | Allows to control which communication channel should receive an alert when leak identified | |
| {Owner} {Account ID} Consumption Alert Exceeded Threshould (Email) | Switch | Allows to control which communication channel should receive an alert when leak identified | |
| {Owner} {Account ID} Consumption Alert Exceeded Threshould (SMS) | Switch | Allows to control which communication channel should receive an alert when leak identified | |

### Per meter

| Entity Name | Type | Description | Additional information |
| ----------------------------------------------------- | ------ | -------------------------------------------------------------------------------- | ------------------------------------------------------ |
| CityMind {Meter Count} Meter Last Read | Sensor | Represents the last read in m³ | Statistics: Total Increment |
| CityMind {Meter Count} Meter Monthly Consumption | Sensor | Represents the monthly consumption in m³ | Statistics: Total Increment |
| CityMind {Meter Count} Meter Today's Consumption | Sensor | Represents the daily consumption in m³ | Statistics: Total Increment |
| CityMind {Meter Count} Meter Yesterday's Consumption | Sensor | Represents the yesterday's consumption in m³ | Statistics: Total Increment |
| CityMind {Meter Count} Meter Consumption Forecast | Sensor | Represents the monthly consumption forecast in m³ | Statistics: Total, reset at the beginning of the month |
| CityMind {Meter Count} Low Rate Consumption Threshold | Sensor | Represents the configuration parameter of low rate consumption's threshold in m³ | Statistics: Measurement |
| CityMind {Meter Count} Low Rate | Sensor | Represents the configuration parameter of low rate in ILS/m³ | Statistics: Measurement |
| CityMind {Meter Count} High Rate | Sensor | Represents the configuration parameter of high rate configuration in ILS/m³ | Statistics: Measurement |
| CityMind {Meter Count} Sewage Rate | Sensor | Represents the configuration parameter of sewage rate configuration in ILS/m³ | Statistics: Measurement |
| CityMind {Meter Count} Low Rate Consumption | Sensor | Represents the consumption below the threshold in m³ | Statistics: Measurement |
| CityMind {Meter Count} High Rate Consumption | Sensor | Represents the consumption above the threshold in m³ | Statistics: Measurement |
| Entity Name | Type | Description | Additional information |
| ------------------------------------------------------ | ------ | -------------------------------------------------------------------------------- | ------------------------------------------------------ |
| {Address} {Meter Count} Last Read | Sensor | Represents the last read in m³ | Statistics: Total Increment |
| {Address} {Meter Count} Monthly Consumption | Sensor | Represents the monthly consumption in m³ | Statistics: Total Increment |
| {Address} {Meter Count} Today's Consumption | Sensor | Represents the daily consumption in m³ | Statistics: Total Increment |
| {Address} {Meter Count} Yesterday's Consumption | Sensor | Represents the yesterday's consumption in m³ | Statistics: Total Increment |
| {Address} {Meter Count} Consumption Forecast | Sensor | Represents the monthly consumption forecast in m³ | Statistics: Total, reset at the beginning of the month |
| {Address} {Meter Count} Low Rate Consumption | Sensor | Represents the consumption below the threshold in m³ | Statistics: Measurement |
| {Address} {Meter Count} High Rate Consumption | Sensor | Represents the consumption above the threshold in | Statistics: Measurement |
| {Address} {Meter Count} Low Rate Consumption Threshold | Number | Represents the configuration parameter of low rate consumption's threshold in | Statistics: Measurement |
| {Address} {Meter Count} Low Rate Cost | Number | Represents the configuration parameter of low rate in ILS/m³ | Statistics: Measurement |
| {Address} {Meter Count} High Rate Cost | Number | Represents the configuration parameter of high rate configuration in ILS/m³ | Statistics: Measurement |
| {Address} {Meter Count} Sewage Cost | Number | Represents the configuration parameter of sewage rate configuration in ILS/m³ | Statistics: Measurement |

_Last read and daily, monthly, low / high rate consumption's sensors are supporting Water energy_
_Low, High, Sewage rates and threshold sensors category is configuration and will be available only when set by the service_

## Services

### Set Cost Parameters

Set cost's parameters for specific meter:

- Low Rate Consumption Threshold - Time to consider a device without activity as AWAY (any value between 10 and 1800 in seconds)
- Low Rate - Low rate per cubic meter (m³) for consumption below the threshold
- High Rate - High rate per cubic meter (m³) for consumption above the threshold
- Sewage Rate - Sewage rate in ILS per cubic meter (m³)
Cost configuration into meter device (per meter) using number entities

More details available in `Developer tools` -> `Services` -> `citymind_water_meter.set_cost_parameters`
- Low Rate Cost - Default 7.955 ILS/m³
- High Rate Cost - Default 14.6 ILS/m³
- Low Rate Cost - Default 7.955 ILS/m³
- Sewage Cost - Default 0 ILS/m³
- Low Rate Consumption Threshold - Default 3.5 m³ (Equivalent to 7m³ per 2 months of 1 person in property)

```yaml
service: citymind_water_meter.set_cost_parameters
data:
device_id: { Meter device ID }
low_rate_consumption_threshold: 7
low_rate: 6.5
high_rate: 13.5
sewage_rate: 3.5
```

_Will reload the integration_
_Default values taken from [gov.il](https://www.gov.il/he/pages/rates_general1) and up to date to January 1st 2024_

### Remove Cost Parameters
## Troubleshooting

Remove cost's parameters for specific meter
### Debug logs

More details available in `Developer tools` -> `Services` -> `citymind_water_meter.remove_cost_parameters`
To set the log level of the component to DEBUG, please set it from the options of the component if installed, otherwise, set it within configuration YAML of HA:

```yaml
service: citymind_water_meter.remove_cost_parameters
data:
device_id: { Meter device ID }
logger:
default: warning
logs:
custom_components.citymind_water_meter: debug
```
_Will reload the integration_

## Endpoints
### Diagnostic file
| Endpoint Name | Method | Description |
| ---------------------------------------- | ------ | --------------------------------------------------------------------------------------------------- |
| /api/citymind_water_meter/list | GET | List all the endpoints available (supporting multiple integrations), available once for integration |
| /api/citymind_water_meter/{ENTRY_ID}/api | GET | JSON of all raw data from the Read Your Meter Pro API, per integration |
In Settings -> Devices & services, look for the device, click on the 3 dots menu and download diagnostic file,
**Authentication: Requires long-living token from HA**

### Examples

#### List

_Request_

```bash
curl https://ha_url:8123/api/citymind_water_meter/list
-H "Accept: application/json"
-H "Authorization: Bearer {token}"
```

#### API Data

```bash
curl https://ha_url:8123/api/citymind_water_meter/{ENTRY_ID}/api
-H "Accept: application/json"
-H "Authorization: Bearer {token}"
```
Diagnostic file contains sensitive details, go over it and clean it or send it directly to my [email](elad.bar@hotmail)
## Example of a History Chart
Expand Down
88 changes: 68 additions & 20 deletions custom_components/citymind_water_meter/__init__.py
Original file line number Diff line number Diff line change
@@ -1,60 +1,108 @@
"""
HA initialization.
This component provides support for EdgeOS based devices.
For more details about this component, please refer to the documentation at
https://github.com/maorcc/citymind_water_meter
"""
import logging
import sys

from homeassistant.config_entries import ConfigEntry
from homeassistant.const import EVENT_HOMEASSISTANT_START
from homeassistant.core import HomeAssistant

from .component.helpers.common import async_set_ha, clear_ha, get_ha
from .configuration.helpers.const import DOMAIN
from .common.consts import DEFAULT_NAME, DOMAIN
from .common.entity_descriptions import PLATFORMS
from .managers.config_manager import ConfigManager
from .managers.coordinator import Coordinator
from .managers.password_manager import PasswordManager
from .models.exceptions import LoginError

_LOGGER = logging.getLogger(__name__)


async def async_setup(hass, config):
async def async_setup(_hass, _config):
return True


async def async_setup_entry(hass: HomeAssistant, entry: ConfigEntry) -> bool:
"""Set up a component."""
"""Set up a EdgeOS component."""
initialized = False

try:
_LOGGER.debug(f"Starting async_setup_entry of {DOMAIN}")
entry.add_update_listener(async_options_updated)
_LOGGER.debug("Setting up")
entry_config = {key: entry.data[key] for key in entry.data}

await async_set_ha(hass, entry)
_LOGGER.debug("Starting up password manager")
await PasswordManager.decrypt(hass, entry_config, entry.entry_id)

initialized = True
_LOGGER.debug("Starting up configuration manager")
config_manager = ConfigManager(hass, entry)
await config_manager.initialize(entry_config)

is_initialized = config_manager.is_initialized

if is_initialized:
_LOGGER.debug("Starting up coordinator")
coordinator = Coordinator(hass, config_manager)

hass.data.setdefault(DOMAIN, {})[entry.entry_id] = coordinator

if hass.is_running:
_LOGGER.debug("Initializing coordinator")
await coordinator.initialize()

else:
_LOGGER.debug("Registering listener for HA started event")
hass.bus.async_listen_once(
EVENT_HOMEASSISTANT_START, coordinator.on_home_assistant_start
)

_LOGGER.info("Finished loading integration")

initialized = is_initialized

_LOGGER.debug(f"Setup status: {is_initialized}")

except LoginError:
_LOGGER.info(f"Failed to login {DEFAULT_NAME} API, cannot log integration")

except Exception as ex:
exc_type, exc_obj, tb = sys.exc_info()
line_number = tb.tb_lineno

_LOGGER.error(f"Failed to setup entry, error: {ex}, line: {line_number}")
_LOGGER.error(
f"Failed to load {DEFAULT_NAME}, error: {ex}, line: {line_number}"
)

return initialized


async def async_unload_entry(hass: HomeAssistant, entry: ConfigEntry):
"""Unload a config entry."""
ha = get_ha(hass, entry.entry_id)
_LOGGER.info(f"Unloading {DOMAIN} integration, Entry ID: {entry.entry_id}")

coordinator: Coordinator = hass.data[DOMAIN][entry.entry_id]

if ha is not None:
await ha.async_remove(entry)
await coordinator.terminate()

clear_ha(hass, entry.entry_id)
for platform in PLATFORMS:
await hass.config_entries.async_forward_entry_unload(entry, platform)

del hass.data[DOMAIN][entry.entry_id]

return True


async def async_options_updated(hass: HomeAssistant, entry: ConfigEntry):
"""Triggered by config entry options updates."""
_LOGGER.info(f"async_options_updated, Entry: {entry.as_dict()} ")
async def async_remove_entry(hass: HomeAssistant, entry: ConfigEntry):
"""Unload a config entry."""
_LOGGER.info(f"Removing {DOMAIN} integration, Entry ID: {entry.entry_id}")

entry_id = entry.entry_id

coordinator: Coordinator = hass.data[DOMAIN][entry_id]

await coordinator.config_manager.remove(entry_id)

ha = get_ha(hass, entry.entry_id)
result = await async_unload_entry(hass, entry)

if ha is not None:
await ha.async_update_entry(entry)
return result
Loading

0 comments on commit 7b3b1a6

Please sign in to comment.