diff --git a/.bumpversion.cfg b/.bumpversion.cfg index 56a6c68..a101966 100644 --- a/.bumpversion.cfg +++ b/.bumpversion.cfg @@ -1,5 +1,5 @@ [bumpversion] -current_version = 1.1.1b1 +current_version = 1.1.1 parse = (?P\d+)(\.(?P\d+))(\.(?P\d+))(?P[bf]*)(?P\d*) commit = True tag = True diff --git a/custom_components/mega/__init__.py b/custom_components/mega/__init__.py index 9776d82..0b84bb4 100644 --- a/custom_components/mega/__init__.py +++ b/custom_components/mega/__init__.py @@ -18,7 +18,8 @@ from .const import DOMAIN, CONF_INVERT, CONF_RELOAD, PLATFORMS, CONF_PORTS, CONF CONF_MQTT_INPUTS, CONF_HTTP, CONF_RESPONSE_TEMPLATE, CONF_ACTION, CONF_GET_VALUE, CONF_ALLOW_HOSTS, \ CONF_CONV_TEMPLATE, CONF_ALL, CONF_FORCE_D, CONF_DEF_RESPONSE, CONF_FORCE_I2C_SCAN, CONF_HEX_TO_FLOAT, \ RGB_COMBINATIONS, CONF_WS28XX, CONF_ORDER, CONF_SMOOTH, CONF_LED, CONF_WHITE_SEP, CONF_CHIP, CONF_RANGE, \ - CONF_FILTER_VALUES, CONF_FILTER_SCALE, CONF_FILTER_LOW, CONF_FILTER_HIGH, CONF_FILL_NA + CONF_FILTER_VALUES, CONF_FILTER_SCALE, CONF_FILTER_LOW, CONF_FILTER_HIGH, CONF_FILL_NA, CONF_MEGA_ID, CONF_ADDR, \ + CONF_1WBUS from .hub import MegaD from .config_flow import ConfigFlow from .http import MegaView @@ -108,6 +109,11 @@ def extender(x): else: raise ValueError('must has "e" in port name') +OWBUS = vol.Schema({ + vol.Required(CONF_PORT): vol.Any(vol.Coerce(int), vol.Coerce(str)), + vol.Required(CONF_MEGA_ID): vol.Coerce(str), + vol.Required(CONF_ADDR): [str], +}) CONFIG_SCHEMA = vol.Schema( { @@ -134,7 +140,8 @@ CONFIG_SCHEMA = vol.Schema( vol.Optional(CONF_FILTER_SCALE): cv.positive_float, vol.Optional(CONF_FILTER_LOW): cv.positive_float, vol.Optional(CONF_FILTER_HIGH): cv.positive_float, - } + }, + vol.Optional(CONF_1WBUS): [OWBUS] } }, extra=vol.ALLOW_EXTRA, diff --git a/custom_components/mega/const.py b/custom_components/mega/const.py index 67b6718..3c4b4f5 100644 --- a/custom_components/mega/const.py +++ b/custom_components/mega/const.py @@ -50,6 +50,8 @@ CONF_FILTER_VALUES = 'filter_values' CONF_FILTER_SCALE = 'filter_scale' CONF_FILTER_LOW = 'filter_low' CONF_FILTER_HIGH = 'filter_high' +CONF_1WBUS = '1wbus' +CONF_ADDR = 'addr' PLATFORMS = [ "light", "switch", diff --git a/custom_components/mega/entities.py b/custom_components/mega/entities.py index 0be72ad..361f24b 100644 --- a/custom_components/mega/entities.py +++ b/custom_components/mega/entities.py @@ -161,15 +161,12 @@ class BaseMegaEntity(CoordinatorEntity, RestoreEntity): ], "name": f'{self._mega_id} port {pt_idx}' if not isinstance(self.port, list) else f'{self._mega_id} {pt_idx}', "manufacturer": 'ab-log.ru', - # "model": self.light.productname, "sw_version": self.mega.fw, "via_device": (DOMAIN, self._mega_id), } @property def lg(self) -> logging.Logger: - # if self._lg is None: - # self._lg = self.mega.lg.getChild(self._name or self.unique_id) return _LOGGER @property diff --git a/custom_components/mega/http.py b/custom_components/mega/http.py index 1e23ba7..af792a2 100644 --- a/custom_components/mega/http.py +++ b/custom_components/mega/http.py @@ -134,7 +134,8 @@ class MegaView(HomeAssistantView): if ret == 'd' and act: await hub.request(cmd=act.replace(':3', f':{v}')) ret = 'd' if hub.force_d else '' - elif port in hub.binary_sensors: + else: + # elif port in hub.binary_sensors: hub.values[port] = data for cb in self.callbacks[hub.id][port]: cb(data) diff --git a/custom_components/mega/i2c.py b/custom_components/mega/i2c.py index 90b90e6..6ce08b6 100644 --- a/custom_components/mega/i2c.py +++ b/custom_components/mega/i2c.py @@ -125,7 +125,7 @@ i2c_classes = { ], 'ptsensor': [ Skip, - Request(delay=1), # запрос на измерение + Request(delay=3), # запрос на измерение DeviceType(DEVICE_CLASS_PRESSURE, PRESSURE_BAR, None), DeviceType(DEVICE_CLASS_TEMPERATURE, TEMP_CELSIUS, None), ], diff --git a/custom_components/mega/manifest.json b/custom_components/mega/manifest.json index 7df91a7..a2534ec 100644 --- a/custom_components/mega/manifest.json +++ b/custom_components/mega/manifest.json @@ -15,5 +15,5 @@ "@andvikt" ], "issue_tracker": "https://github.com/andvikt/mega_hacs/issues", - "version": "v1.1.1b1" + "version": "v1.1.1" } \ No newline at end of file diff --git a/custom_components/mega/sensor.py b/custom_components/mega/sensor.py index 579bb7c..58a90cb 100644 --- a/custom_components/mega/sensor.py +++ b/custom_components/mega/sensor.py @@ -6,7 +6,7 @@ import struct from homeassistant.components.sensor import ( PLATFORM_SCHEMA as SENSOR_SCHEMA, DEVICE_CLASS_TEMPERATURE, - DEVICE_CLASS_HUMIDITY + DEVICE_CLASS_HUMIDITY, SensorEntity ) from homeassistant.config_entries import ConfigEntry from homeassistant.const import ( @@ -108,30 +108,34 @@ async def async_setup_entry(hass: HomeAssistant, config_entry: ConfigEntry, asyn async_add_devices(devices) -class FilterBadValues(MegaPushEntity): +class FilterBadValues(MegaPushEntity, SensorEntity): def __init__(self, *args, **kwargs): self._prev_value = None super().__init__(*args, **kwargs) def filter_value(self, value): - if value \ - in self.filter_values \ - or (self.filter_low is not None and value < self.filter_low) \ - or (self.filter_high is not None and value > self.filter_high) \ - or ( - self._prev_value is not None - and self.filter_scale is not None - and ( - abs(value - self._prev_value) / self._prev_value > self.filter_scale - ) - ): - if self.fill_na == 'last': - value = self._prev_value - else: - value = None - self._prev_value = value - return value + try: + if value \ + in self.filter_values \ + or (self.filter_low is not None and value < self.filter_low) \ + or (self.filter_high is not None and value > self.filter_high) \ + or ( + self._prev_value is not None + and self.filter_scale is not None + and ( + abs(value - self._prev_value) / self._prev_value > self.filter_scale + ) + ): + if self.fill_na == 'last': + value = self._prev_value + else: + value = None + self._prev_value = value + return value + except Exception as exc: + lg.exception(f'while parsing value') + return None @property def filter_values(self): @@ -191,28 +195,32 @@ class MegaI2C(FilterBadValues): return self._device_class @property - def unit_of_measurement(self): + def native_unit_of_measurement(self): return self._unit_of_measurement @property - def state(self): - ret = self.mega.values.get(self._params) - if self.customize.get(CONF_HEX_TO_FLOAT): - try: - ret = struct.unpack('!f', bytes.fromhex(ret))[0] - except: - self.lg.warning(f'could not convert {ret} form hex to float') - tmpl: Template = self.customize.get(CONF_CONV_TEMPLATE, self.customize.get(CONF_VALUE_TEMPLATE)) + def native_value(self): try: - ret = float(ret) - if tmpl is not None and self.hass is not None: - tmpl.hass = self.hass - ret = tmpl.async_render({'value': ret}) - except: - ret = ret - ret = self.filter_value(ret) - if ret is not None: - return str(ret) + ret = self.mega.values.get(self._params) + if self.customize.get(CONF_HEX_TO_FLOAT): + try: + ret = struct.unpack('!f', bytes.fromhex(ret))[0] + except: + self.lg.warning(f'could not convert {ret} form hex to float') + tmpl: Template = self.customize.get(CONF_CONV_TEMPLATE, self.customize.get(CONF_VALUE_TEMPLATE)) + try: + ret = float(ret) + if tmpl is not None and self.hass is not None: + tmpl.hass = self.hass + ret = tmpl.async_render({'value': ret}) + except: + ret = ret + ret = self.filter_value(ret) + if ret is not None: + return str(ret) + except Exception: + lg.exception('while getting value') + return None @property def device_class(self): @@ -244,7 +252,7 @@ class Mega1WSensor(FilterBadValues): self.prev_value = None @property - def unit_of_measurement(self): + def native_unit_of_measurement(self): _u = self.customize.get(CONF_UNIT_OF_MEASUREMENT, None) if _u is None: return self._unit_of_measurement @@ -275,49 +283,53 @@ class Mega1WSensor(FilterBadValues): return self._device_class @property - def state(self): - ret = None - if not hasattr(self, 'key'): - return None - if self.key: - try: - ret = self.mega.values.get(self.port, {}) - if isinstance(ret, dict): - ret = ret.get('value', {}) + def native_value(self): + try: + ret = None + if not hasattr(self, 'key'): + return None + if self.key: + try: + ret = self.mega.values.get(self.port, {}) if isinstance(ret, dict): - ret = ret.get(self.key) - except: - self.lg.error(self.mega.values.get(self.port, {}).get('value', {})) - return - else: - ret = self.mega.values.get(self.port, {}).get('value') - if ret is None and self.fill_na == 'fill_na' and self.prev_value is not None: - ret = self.prev_value - elif ret is None and self.fill_na == 'fill_na' and self._state is not None: - ret = self._state.state - try: - ret = float(ret) - ret = str(ret) - except: - self.lg.debug(f'could not convert to float "{ret}"') - ret = self.prev_value - if self.customize.get(CONF_HEX_TO_FLOAT): + ret = ret.get('value', {}) + if isinstance(ret, dict): + ret = ret.get(self.key) + except: + self.lg.error(self.mega.values.get(self.port, {}).get('value', {})) + return + else: + ret = self.mega.values.get(self.port, {}).get('value') + if ret is None and self.fill_na == 'fill_na' and self.prev_value is not None: + ret = self.prev_value + elif ret is None and self.fill_na == 'fill_na' and self._state is not None: + ret = self._state.state try: - ret = struct.unpack('!f', bytes.fromhex(ret))[0] + ret = float(ret) + ret = str(ret) except: - self.lg.warning(f'could not convert {ret} form hex to float') - tmpl: Template = self.customize.get(CONF_CONV_TEMPLATE, self.customize.get(CONF_VALUE_TEMPLATE)) - try: - ret = float(ret) - if tmpl is not None and self.hass is not None: - tmpl.hass = self.hass - ret = tmpl.async_render({'value': ret}) - except: - pass - ret = self.filter_value(ret) - self.prev_value = ret - if ret is not None: - return str(ret) + self.lg.debug(f'could not convert to float "{ret}"') + ret = self.prev_value + if self.customize.get(CONF_HEX_TO_FLOAT): + try: + ret = struct.unpack('!f', bytes.fromhex(ret))[0] + except: + self.lg.warning(f'could not convert {ret} form hex to float') + tmpl: Template = self.customize.get(CONF_CONV_TEMPLATE, self.customize.get(CONF_VALUE_TEMPLATE)) + try: + ret = float(ret) + if tmpl is not None and self.hass is not None: + tmpl.hass = self.hass + ret = tmpl.async_render({'value': ret}) + except: + pass + ret = self.filter_value(ret) + self.prev_value = ret + if ret is not None: + return str(ret) + except Exception: + lg.exception('while parsing state') + return None @property def name(self):