Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: implement device info #26

Merged
merged 3 commits into from
Jan 3, 2022
Merged
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
13 changes: 10 additions & 3 deletions custom_components/wibeee/api.py
Original file line number Diff line number Diff line change
Expand Up @@ -31,11 +31,18 @@ async def async_fetch_device_info(self, retries: int):
devices = await self.async_fetch_url(f'http://{self.host}/services/user/devices.xml', retries)
device_id = devices['devices']['id']

var_names = ['macAddr', 'softVersion', 'model', 'ipAddr']
var_ids = [f"{quote_plus(device_id)}.{name}" for name in var_names]
values = await self.async_fetch_url(f'http://{self.host}/services/user/values.xml?var={"&".join(var_ids)}', retries)

# <values><variable><id>macAddr</id><value>11:11:11:11:11:11</value></variable></values>
values = await self.async_fetch_url(f'http://{self.host}/services/user/values.xml?var={quote_plus(device_id)}.macAddr', retries)
mac_addr = values['values']['variable']['value']
device_vars = {var['id']: var['value'] for var in values['values']['variable']}

return dict(id=device_id, mac_addr=mac_addr.replace(":", "").lower()) if device_id and mac_addr else None
return {
**device_vars,
'macAddr': device_vars['macAddr'].replace(':', ''),
'id': device_id,
} if len(device_vars) == len(var_names) else None

async def async_fetch_url(self, url, retries: int = 0):
async def fetch_with_retries(try_n):
Expand Down
5 changes: 3 additions & 2 deletions custom_components/wibeee/config_flow.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@

from .api import WibeeeAPI
from .const import (DOMAIN, DEFAULT_SCAN_INTERVAL)
from .util import short_mac

_LOGGER = logging.getLogger(__name__)

Expand All @@ -26,9 +27,9 @@ async def validate_input(hass: HomeAssistant, user_input: dict) -> [str, str, di
except Exception as e:
raise NoDeviceInfo from e

mac_addr = format_mac(device['mac_addr'])
mac_addr = format_mac(device['macAddr'])
unique_id = mac_addr
name = f"Wibeee {mac_addr.replace(':', '')[-6:].upper()}"
name = f"Wibeee {short_mac(mac_addr)}"

return name, unique_id, {CONF_HOST: user_input[CONF_HOST], }

Expand Down
40 changes: 39 additions & 1 deletion custom_components/wibeee/sensor.py
Original file line number Diff line number Diff line change
Expand Up @@ -40,12 +40,14 @@
from homeassistant.core import HomeAssistant, callback
from homeassistant.exceptions import PlatformNotReady
from homeassistant.helpers.aiohttp_client import async_get_clientsession
from homeassistant.helpers.entity import DeviceInfo
from homeassistant.helpers.entity_platform import AddEntitiesCallback
from homeassistant.helpers.event import async_track_time_interval
from homeassistant.util import slugify

from .api import WibeeeAPI
from .const import (DOMAIN, DEFAULT_SCAN_INTERVAL, DEFAULT_TIMEOUT)
from .util import short_mac

_LOGGER = logging.getLogger(__name__)

Expand All @@ -72,6 +74,20 @@
'energia_reactiva_cap': ['Capacitive_Reactive_Energy', 'Capacitive Reactive Energy', 'VArCh', DEVICE_CLASS_ENERGY]
}

KNOWN_MODELS = {
'WBM': 'Wibeee 1Ph',
'WBT': 'Wibeee 3Ph',
'WTD': 'Wibeee 3Ph RN',
'WX2': 'Wibeee MAX 2S',
'WX3': 'Wibeee MAX 3S',
'WXX': 'Wibeee MAX MS',
'WBB': 'Wibeee BOX',
'WB3': 'Wibeee BOX S3P',
'W3P': 'Wibeee 3Ph 3W',
'WGD': 'Wibeee GND',
'WBP': 'Wibeee PLUG',
}


async def async_setup_platform(hass, config, async_add_entities, discovery_info=None):
"""Import existing configuration from YAML."""
Expand Down Expand Up @@ -126,7 +142,7 @@ class WibeeeSensor(SensorEntity):
def __init__(self, device, xml_name: str, sensor_phase: str, sensor_type: str, sensor_value):
"""Initialize the sensor."""
ha_name, friendly_name, unit, device_class = SENSOR_TYPES[sensor_type]
[device_name, mac_addr] = [device['id'], device['mac_addr']]
[device_name, mac_addr] = [device['id'], device['macAddr']]
entity_id = slugify(f"{DOMAIN} {mac_addr} {friendly_name} L{sensor_phase}")
self._xml_name = xml_name
self._attr_native_unit_of_measurement = unit
Expand All @@ -137,6 +153,7 @@ def __init__(self, device, xml_name: str, sensor_phase: str, sensor_type: str, s
self._attr_unique_id = f"_{mac_addr}_{ha_name.lower()}_{sensor_phase}"
self._attr_name = f"{device_name} {friendly_name} L{sensor_phase}"
self._attr_should_poll = False
self._attr_device_info = _make_device_info(device, sensor_phase)
self.entity_id = f"sensor.{entity_id}" # we don't want this derived from the name

@callback
Expand All @@ -154,3 +171,24 @@ def make_device_sensors(device, status) -> list['WibeeeSensor']:
phase_values = [(key, value, key[4:].split("_", 1)) for key, value in status.items() if key.startswith('fase')]
known_values = [(key, phase, stype, value) for (key, value, (phase, stype)) in phase_values]
return [WibeeeSensor(device, key, phase, stype, value) for (key, phase, stype, value) in known_values if stype in SENSOR_TYPES]


def _make_device_info(device, sensor_phase) -> DeviceInfo:
mac_addr = device['macAddr']
is_clamp = sensor_phase != '4'

device_name = f'Wibeee {short_mac(mac_addr)}'
device_model = KNOWN_MODELS.get(device['model'], 'Wibeee Energy Meter')

return DeviceInfo(
# identifiers and links
identifiers={(DOMAIN, f'{mac_addr}_L{sensor_phase}' if is_clamp else mac_addr)},
via_device=(DOMAIN, f'{mac_addr}') if is_clamp else None,

# and now for the humans :)
name=device_name if not is_clamp else f"{device_name} Line {sensor_phase}",
model=device_model if not is_clamp else f'{device_model} Clamp',
manufacturer='Smilics',
configuration_url=f"http://{device['ipAddr']}/" if not is_clamp else None,
sw_version=f"{device['softVersion']}" if not is_clamp else None,
)
3 changes: 3 additions & 0 deletions custom_components/wibeee/util.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
def short_mac(mac_addr):
"""Returns the last 6 chars of the MAC address for showing in UI."""
return mac_addr.replace(':', '')[-6:].upper()