Open ildar170975 opened 2 years ago
Confirm! I updated 2 minutes before I read this message )
With a Xiaomi Miio integration - same unavailable sensors.
Yes, they are unavailable for me. In any integration.
FYI Related issues with an official integration: https://github.com/home-assistant/core/issues/76646 https://github.com/rytilahti/python-miio/issues/1489
I removed everything related to the battery from the integration and now all values except the battery have appeared.
I removed everything related to the battery
Could you explain how you did it?
Delete all rows and blocks with the battery. ` import logging from collections import defaultdict
import click import json from miio.click_common import command, format_output from miio.device import Device
_LOGGER = logging.getLogger(name)
MODEL_AIRQUALITYMONITOR_S1 = 'cgllc.airmonitor.s1'
AVAILABLE_PROPERTIES_COMMON = [ 'battery_state', 'co2', 'humidity', 'pm25' , 'temperature', 'tvoc']
AVAILABLE_PROPERTIES = { MODEL_AIRQUALITYMONITOR_S1: AVAILABLE_PROPERTIES_COMMON, }
class AirQualityMonitorStatus: """Container of air quality monitor status."""
def __init__(self, data):
self.data = data
@property
def power(self) -> str:
"""Current power state."""
return self.data["power"]
@property
def is_on(self) -> bool:
"""Return True if the device is turned on."""
return self.power == "on"
@property
def temperature(self) -> bool:
"""Return True if the device's usb is on."""
return self.data["temperature"]
@property
def humidity(self) -> int:
"""Air quality index value. (0...600)."""
return self.data["humidity"]
@property
def co2(self) -> int:
"""Air quality index value. (0...600)."""
return self.data["co2"]
@property
def tvoc(self) -> int:
"""Current battery level (0...100)."""
return self.data["tvoc"]
@property
def pm25(self) -> bool:
"""Display a clock instead the AQI."""
return self.data["pm25"]
@property
def battery_state(self) -> str:
"""Return the begin of the night time."""
return self.data["battery_state"]
def __repr__(self) -> str:
s = "<AirQualityMonitorStatus humidity=%s, " \
"co2=%s, " \
"tvoc=%s, " \
"pm25=%s, " \
"battery=%s, " \
"battery_state=%s>" % \
(self.humidity,
self.co2,
self.tvoc,
self.pm25,
self.battery_state,
)
return s
def __json__(self):
return self.data
class AirQualityMonitor(Device): """Xiaomi PM2.5 Air Quality Monitor.""" def init(self, ip: str = None, token: str = None, start_id: int = 0, debug: int = 0, lazy_discover: bool = True, model: str = MODEL_AIRQUALITYMONITOR_S1) -> None: super().init(ip, token, start_id, debug, lazy_discover, model=model)
if model not in AVAILABLE_PROPERTIES:
_LOGGER.error("Device model %s unsupported. Falling back to %s.", model, self.model)
self.device_info = None
@command(
default_output=format_output(
""
)
)
def status(self) -> AirQualityMonitorStatus:
"""Return device status."""
properties = AVAILABLE_PROPERTIES[self.model]
values = self.send(
"get_prop",
properties
)
properties_count = len(properties)
values_count = len(values)
if properties_count != values_count:
_LOGGER.error(
"Count (%s) of requested properties does not match the "
"count (%s) of received values.",
properties_count, values_count)
return AirQualityMonitorStatus(
defaultdict(lambda: None, values))
@command(
default_output=format_output("Powering on"),
)
def on(self):
"""Power on."""
return self.send("set_power", ["on"])
@command(
default_output=format_output("Powering off"),
)
def off(self):
"""Power off."""
return self.send("set_power", ["off"])
@command(
click.argument("display_clock", type=bool),
default_output=format_output(
lambda led: "Turning on display clock"
if led else "Turning off display clock"
)
)
def set_display_clock(self, display_clock: bool):
"""Enable/disable displaying a clock instead the AQI."""
if display_clock:
self.send("set_time_state", ["on"])
else:
self.send("set_time_state", ["off"])
@command(
click.argument("auto_close", type=bool),
default_output=format_output(
lambda led: "Turning on auto close"
if led else "Turning off auto close"
)
)
def set_auto_close(self, auto_close: bool):
"""Purpose unknown."""
if auto_close:
self.send("set_auto_close", ["on"])
else:
self.send("set_auto_close", ["off"])
@command(
click.argument("night_mode", type=bool),
default_output=format_output(
lambda led: "Turning on night mode"
if led else "Turning off night mode"
)
)
def set_night_mode(self, night_mode: bool):
"""Decrease the brightness of the display."""
if night_mode:
self.send("set_night_state", ["on"])
else:
self.send("set_night_state", ["off"])
@command(
click.argument("begin_hour", type=int),
click.argument("begin_minute", type=int),
click.argument("end_hour", type=int),
click.argument("end_minute", type=int),
default_output=format_output(
"Setting night time to {begin_hour}:{begin_minute} - {end_hour}:{end_minute}")
)
def set_night_time(self, begin_hour: int, begin_minute: int,
end_hour: int, end_minute: int):
"""Enable night mode daily at bedtime."""
begin = begin_hour * 3600 + begin_minute * 60
end = end_hour * 3600 + end_minute * 60
if begin < 0 or begin > 86399 or end < 0 or end > 86399:
raise Exception("Begin or/and end time invalid.")
self.send("set_night_time", [begin, end])
"""Support for Xiaomi Mi Air Quality Monitor (PM2.5).""" import logging
import voluptuous as vol
from homeassistant.components.sensor import PLATFORM_SCHEMA from homeassistant.const import CONF_HOST, CONF_NAME, CONF_TOKEN from homeassistant.exceptions import PlatformNotReady import homeassistant.helpers.config_validation as cv from homeassistant.helpers.entity import Entity
_LOGGER = logging.getLogger(name)
DEFAULT_NAME = 'clear_grass' DATA_KEY = 'sensor.clear_grass'
PLATFORM_SCHEMA = PLATFORM_SCHEMA.extend({ vol.Required(CONF_HOST): cv.string, vol.Required(CONF_TOKEN): vol.All(cv.string, vol.Length(min=32, max=32)), vol.Optional(CONF_NAME, default=DEFAULT_NAME): cv.string, })
ATTR_TEMPERATURE = 'temperature' ATTR_HUMIDITY = 'humidity' ATTR_CO2 = 'co2' ATTR_TVOC = 'tvoc' ATTR_PM25 = 'pm25'
ATTR_BATTERY_STATE = 'battery_state'
ATTR_MODEL = 'model'
SUCCESS = ['ok']
async def async_setup_platform(hass, config, async_add_entities, discovery_info=None): """Set up the sensor from config.""" if DATA_KEY not in hass.data: hass.data[DATA_KEY] = {}
host = config.get(CONF_HOST)
name = config.get(CONF_NAME)
token = config.get(CONF_TOKEN)
_LOGGER.info("Initializing with host %s (token %s...)", host, token[:5])
try:
air_quality_monitor = AirQualityMonitor(host, token)
device_info = air_quality_monitor.info()
model = device_info.model
unique_id = "{}-{}".format(model, device_info.mac_address)
_LOGGER.info("%s %s %s detected",
model,
device_info.firmware_version,
device_info.hardware_version)
device = ClearGrassMonitor(
name, air_quality_monitor, model, unique_id)
except Exception:
raise PlatformNotReady
hass.data[DATA_KEY][host] = device
async_add_entities([device], update_before_add=True)
class ClearGrassMonitor(Entity): """Representation of a Xiaomi Air Quality Monitor."""
def __init__(self, name, device, model, unique_id):
"""Initialize the entity."""
self._name = name
self._device = device
self._model = model
self._unique_id = unique_id
self._icon = 'mdi:cloud'
self._unit_of_measurement = 'AQI'
self._available = None
self._state = None
self._state_attrs = {
ATTR_TEMPERATURE: None,
ATTR_HUMIDITY: None,
ATTR_CO2: None,
ATTR_TVOC: None,
#ATTR_PM25: None,
ATTR_BATTERY_STATE: None,
ATTR_MODEL: self._model,
}
@property
def should_poll(self):
"""Poll the miio device."""
return True
@property
def unique_id(self):
"""Return an unique ID."""
return self._unique_id
@property
def name(self):
"""Return the name of this entity, if any."""
return self._name
@property
def unit_of_measurement(self):
"""Return the unit of measurement of this entity, if any."""
return self._unit_of_measurement
@property
def icon(self):
"""Return the icon to use for device if any."""
return self._icon
@property
def available(self):
"""Return true when state is known."""
return self._available
@property
def state(self):
"""Return the state of the device."""
return self._state
@property
def extra_state_attributes(self):
"""Return the state attributes of the device."""
return self._state_attrs
async def async_update(self):
"""Fetch state from the miio device."""
try:
state = await self.hass.async_add_executor_job(self._device.status)
self._available = True
self._state = state.pm25
self._state_attrs.update({
ATTR_TEMPERATURE: state.temperature,
ATTR_HUMIDITY: state.humidity,
ATTR_CO2: state.co2,
ATTR_TVOC: state.tvoc,
# ATTR_PM25:state.pm25,
ATTR_BATTERY_STATE:state.battery_state,
})
except Exception as ex:
self._available = False
_LOGGER.error("Got exception while fetching the state: %s", ex) `
i.e. by changing a source code.... So sad.
currently, only so.
@akarpych Thanks for help!
So I've removed battery state request from the code but haven't tested it. You can try the hotfix form here: https://github.com/Cheaterdev/clear_grass-ha/tree/firmware-update
And if it works - I'll update the main branch.
And if it works - I'll update the main branch.
Sorry, does it mean that battery info will not be available? battery level, battery_charging
And if it works - I'll update the main branch.
Sorry, does it mean that battery info will not be available? battery level, battery_charging
As far I can see - it's should be requested in the other way. Currently I'm in the Ukrainian army so I don't have a possibility to make and test a proper fix. At least other values will be presented.
Currently I'm in the Ukrainian army so I don't have a possibility to make and test a proper fix
Take care if yourself!
You can try the hotfix form here:
What I did is:
Update: very strange - see for yourself:
Update: not, that was not a mistake - same error I see in logs now after HA restart:
2022-08-14 16:33:32.239 ERROR (MainThread) [homeassistant.loader] Unexpected exception importing platform custom_components.clear_grass.sensor
Traceback (most recent call last):
File "/usr/src/homeassistant/homeassistant/loader.py", line 657, in get_platform
cache[full_name] = self._import_platform(platform_name)
File "/usr/src/homeassistant/homeassistant/loader.py", line 674, in _import_platform
return importlib.import_module(f"{self.pkg_path}.{platform_name}")
File "/usr/local/lib/python3.10/importlib/__init__.py", line 126, in import_module
return _bootstrap._gcd_import(name[level:], package, level)
File "<frozen importlib._bootstrap>", line 1050, in _gcd_import
File "<frozen importlib._bootstrap>", line 1027, in _find_and_load
File "<frozen importlib._bootstrap>", line 1006, in _find_and_load_unlocked
File "<frozen importlib._bootstrap>", line 688, in _load_unlocked
File "<frozen importlib._bootstrap_external>", line 879, in exec_module
File "<frozen importlib._bootstrap_external>", line 1017, in get_code
File "<frozen importlib._bootstrap_external>", line 947, in source_to_code
File "<frozen importlib._bootstrap>", line 241, in _call_with_frames_removed
File "/config/custom_components/clear_grass/sensor.py", line 76
"battery_state=%s>" % \
IndentationError: unexpected indent
Then I just removed this line:
Then after HA restart there is no errors in log - but also no data for Cleargrass sensor.
What I posted above works. It does not show only the battery %
@akarpych could you repost your code again? That post contains a strangely formatted text.
from collections import defaultdict
import click
import json
from miio.click_common import command, format_output
from miio.device import Device
_LOGGER = logging.getLogger(__name__)
MODEL_AIRQUALITYMONITOR_S1 = 'cgllc.airmonitor.s1'
AVAILABLE_PROPERTIES_COMMON = [ 'battery_state', 'co2', 'humidity', 'pm25' , 'temperature', 'tvoc']
AVAILABLE_PROPERTIES = {
MODEL_AIRQUALITYMONITOR_S1: AVAILABLE_PROPERTIES_COMMON,
}
class AirQualityMonitorStatus:
"""Container of air quality monitor status."""
def __init__(self, data):
self.data = data
@property
def power(self) -> str:
"""Current power state."""
return self.data["power"]
@property
def is_on(self) -> bool:
"""Return True if the device is turned on."""
return self.power == "on"
@property
def temperature(self) -> bool:
"""Return True if the device's usb is on."""
return self.data["temperature"]
@property
def humidity(self) -> int:
"""Air quality index value. (0...600)."""
return self.data["humidity"]
@property
def co2(self) -> int:
"""Air quality index value. (0...600)."""
return self.data["co2"]
@property
def tvoc(self) -> int:
"""Current battery level (0...100)."""
return self.data["tvoc"]
@property
def pm25(self) -> bool:
"""Display a clock instead the AQI."""
return self.data["pm25"]
@property
def battery_state(self) -> str:
"""Return the begin of the night time."""
return self.data["battery_state"]
def __repr__(self) -> str:
s = "<AirQualityMonitorStatus humidity=%s, " \
"co2=%s, " \
"tvoc=%s, " \
"pm25=%s, " \
"battery_state=%s>" % \
(self.humidity,
self.co2,
self.tvoc,
self.pm25,
self.battery_state,
)
return s
def __json__(self):
return self.data
class AirQualityMonitor(Device):
"""Xiaomi PM2.5 Air Quality Monitor."""
def __init__(self, ip: str = None, token: str = None, start_id: int = 0,
debug: int = 0, lazy_discover: bool = True,
model: str = MODEL_AIRQUALITYMONITOR_S1) -> None:
super().__init__(ip, token, start_id, debug, lazy_discover, model=model)
if model not in AVAILABLE_PROPERTIES:
_LOGGER.error("Device model %s unsupported. Falling back to %s.", model, self.model)
self.device_info = None
@command(
default_output=format_output(
""
)
)
def status(self) -> AirQualityMonitorStatus:
"""Return device status."""
properties = AVAILABLE_PROPERTIES[self.model]
values = self.send(
"get_prop",
properties
)
properties_count = len(properties)
values_count = len(values)
if properties_count != values_count:
_LOGGER.error(
"Count (%s) of requested properties does not match the "
"count (%s) of received values.",
properties_count, values_count)
return AirQualityMonitorStatus(
defaultdict(lambda: None, values))
@command(
default_output=format_output("Powering on"),
)
def on(self):
"""Power on."""
return self.send("set_power", ["on"])
@command(
default_output=format_output("Powering off"),
)
def off(self):
"""Power off."""
return self.send("set_power", ["off"])
@command(
click.argument("display_clock", type=bool),
default_output=format_output(
lambda led: "Turning on display clock"
if led else "Turning off display clock"
)
)
def set_display_clock(self, display_clock: bool):
"""Enable/disable displaying a clock instead the AQI."""
if display_clock:
self.send("set_time_state", ["on"])
else:
self.send("set_time_state", ["off"])
@command(
click.argument("auto_close", type=bool),
default_output=format_output(
lambda led: "Turning on auto close"
if led else "Turning off auto close"
)
)
def set_auto_close(self, auto_close: bool):
"""Purpose unknown."""
if auto_close:
self.send("set_auto_close", ["on"])
else:
self.send("set_auto_close", ["off"])
@command(
click.argument("night_mode", type=bool),
default_output=format_output(
lambda led: "Turning on night mode"
if led else "Turning off night mode"
)
)
def set_night_mode(self, night_mode: bool):
"""Decrease the brightness of the display."""
if night_mode:
self.send("set_night_state", ["on"])
else:
self.send("set_night_state", ["off"])
@command(
click.argument("begin_hour", type=int),
click.argument("begin_minute", type=int),
click.argument("end_hour", type=int),
click.argument("end_minute", type=int),
default_output=format_output(
"Setting night time to {begin_hour}:{begin_minute} - {end_hour}:{end_minute}")
)
def set_night_time(self, begin_hour: int, begin_minute: int,
end_hour: int, end_minute: int):
"""Enable night mode daily at bedtime."""
begin = begin_hour * 3600 + begin_minute * 60
end = end_hour * 3600 + end_minute * 60
if begin < 0 or begin > 86399 or end < 0 or end > 86399:
raise Exception("Begin or/and end time invalid.")
self.send("set_night_time", [begin, end])
"""Support for Xiaomi Mi Air Quality Monitor (PM2.5)."""
import logging
import voluptuous as vol
from homeassistant.components.sensor import PLATFORM_SCHEMA
from homeassistant.const import CONF_HOST, CONF_NAME, CONF_TOKEN
from homeassistant.exceptions import PlatformNotReady
import homeassistant.helpers.config_validation as cv
from homeassistant.helpers.entity import Entity
_LOGGER = logging.getLogger(__name__)
DEFAULT_NAME = 'clear_grass'
DATA_KEY = 'sensor.clear_grass'
PLATFORM_SCHEMA = PLATFORM_SCHEMA.extend({
vol.Required(CONF_HOST): cv.string,
vol.Required(CONF_TOKEN): vol.All(cv.string, vol.Length(min=32, max=32)),
vol.Optional(CONF_NAME, default=DEFAULT_NAME): cv.string,
})
ATTR_TEMPERATURE = 'temperature'
ATTR_HUMIDITY = 'humidity'
ATTR_CO2 = 'co2'
ATTR_TVOC = 'tvoc'
ATTR_PM25 = 'pm25'
ATTR_BATTERY_STATE = 'battery_state'
ATTR_MODEL = 'model'
SUCCESS = ['ok']
async def async_setup_platform(hass, config, async_add_entities,
discovery_info=None):
"""Set up the sensor from config."""
if DATA_KEY not in hass.data:
hass.data[DATA_KEY] = {}
host = config.get(CONF_HOST)
name = config.get(CONF_NAME)
token = config.get(CONF_TOKEN)
_LOGGER.info("Initializing with host %s (token %s...)", host, token[:5])
try:
air_quality_monitor = AirQualityMonitor(host, token)
device_info = air_quality_monitor.info()
model = device_info.model
unique_id = "{}-{}".format(model, device_info.mac_address)
_LOGGER.info("%s %s %s detected",
model,
device_info.firmware_version,
device_info.hardware_version)
device = ClearGrassMonitor(
name, air_quality_monitor, model, unique_id)
except Exception:
raise PlatformNotReady
hass.data[DATA_KEY][host] = device
async_add_entities([device], update_before_add=True)
class ClearGrassMonitor(Entity):
"""Representation of a Xiaomi Air Quality Monitor."""
def __init__(self, name, device, model, unique_id):
"""Initialize the entity."""
self._name = name
self._device = device
self._model = model
self._unique_id = unique_id
self._icon = 'mdi:cloud'
self._unit_of_measurement = 'AQI'
self._available = None
self._state = None
self._state_attrs = {
ATTR_TEMPERATURE: None,
ATTR_HUMIDITY: None,
ATTR_CO2: None,
ATTR_TVOC: None,
#ATTR_PM25: None,
ATTR_BATTERY_STATE: None,
ATTR_MODEL: self._model,
}
@property
def should_poll(self):
"""Poll the miio device."""
return True
@property
def unique_id(self):
"""Return an unique ID."""
return self._unique_id
@property
def name(self):
"""Return the name of this entity, if any."""
return self._name
@property
def unit_of_measurement(self):
"""Return the unit of measurement of this entity, if any."""
return self._unit_of_measurement
@property
def icon(self):
"""Return the icon to use for device if any."""
return self._icon
@property
def available(self):
"""Return true when state is known."""
return self._available
@property
def state(self):
"""Return the state of the device."""
return self._state
@property
def extra_state_attributes(self):
"""Return the state attributes of the device."""
return self._state_attrs
async def async_update(self):
"""Fetch state from the miio device."""
try:
state = await self.hass.async_add_executor_job(self._device.status)
self._available = True
self._state = state.pm25
self._state_attrs.update({
ATTR_TEMPERATURE: state.temperature,
ATTR_HUMIDITY: state.humidity,
ATTR_CO2: state.co2,
ATTR_TVOC: state.tvoc,
# ATTR_PM25:state.pm25,
ATTR_BATTERY_STATE:state.battery_state,
})
except Exception as ex:
self._available = False
_LOGGER.error("Got exception while fetching the state: %s", ex)
@akarpych No, this code gives errors on HA restart:
2022-08-14 17:32:17.846 ERROR (MainThread) [homeassistant.loader] Unexpected exception importing platform custom_components.clear_grass.sensor
Traceback (most recent call last):
File "/usr/src/homeassistant/homeassistant/loader.py", line 657, in get_platform
cache[full_name] = self._import_platform(platform_name)
File "/usr/src/homeassistant/homeassistant/loader.py", line 674, in _import_platform
return importlib.import_module(f"{self.pkg_path}.{platform_name}")
File "/usr/local/lib/python3.10/importlib/__init__.py", line 126, in import_module
return _bootstrap._gcd_import(name[level:], package, level)
File "<frozen importlib._bootstrap>", line 1050, in _gcd_import
File "<frozen importlib._bootstrap>", line 1027, in _find_and_load
File "<frozen importlib._bootstrap>", line 1006, in _find_and_load_unlocked
File "<frozen importlib._bootstrap>", line 688, in _load_unlocked
File "<frozen importlib._bootstrap_external>", line 879, in exec_module
File "<frozen importlib._bootstrap_external>", line 1017, in get_code
File "<frozen importlib._bootstrap_external>", line 947, in source_to_code
File "<frozen importlib._bootstrap>", line 241, in _call_with_frames_removed
File "/config/custom_components/clear_grass/sensor.py", line 20
"""Container of air quality monitor status."""
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
IndentationError: expected an indented block after class definition on line 19
2022-08-14 17:32:17.848 ERROR (MainThread) [homeassistant.config] Platform error: sensor
Traceback (most recent call last):
File "/usr/src/homeassistant/homeassistant/loader.py", line 657, in get_platform
cache[full_name] = self._import_platform(platform_name)
File "/usr/src/homeassistant/homeassistant/loader.py", line 674, in _import_platform
return importlib.import_module(f"{self.pkg_path}.{platform_name}")
File "/usr/local/lib/python3.10/importlib/__init__.py", line 126, in import_module
return _bootstrap._gcd_import(name[level:], package, level)
File "<frozen importlib._bootstrap>", line 1050, in _gcd_import
File "<frozen importlib._bootstrap>", line 1027, in _find_and_load
File "<frozen importlib._bootstrap>", line 1006, in _find_and_load_unlocked
File "<frozen importlib._bootstrap>", line 688, in _load_unlocked
File "<frozen importlib._bootstrap_external>", line 879, in exec_module
File "<frozen importlib._bootstrap_external>", line 1017, in get_code
File "<frozen importlib._bootstrap_external>", line 947, in source_to_code
File "<frozen importlib._bootstrap>", line 241, in _call_with_frames_removed
File "/config/custom_components/clear_grass/sensor.py", line 20
"""Container of air quality monitor status."""
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
IndentationError: expected an indented block after class definition on line 19
The above exception was the direct cause of the following exception:
Traceback (most recent call last):
File "/usr/src/homeassistant/homeassistant/config.py", line 878, in async_process_component_config
platform = p_integration.get_platform(domain)
File "/usr/src/homeassistant/homeassistant/loader.py", line 666, in get_platform
raise ImportError(
ImportError: Exception importing custom_components.clear_grass.sensor
2022-08-14 17:32:17.850 ERROR (MainThread) [homeassistant.loader] Unexpected exception importing platform custom_components.clear_grass.sensor
Traceback (most recent call last):
File "/usr/src/homeassistant/homeassistant/loader.py", line 657, in get_platform
cache[full_name] = self._import_platform(platform_name)
File "/usr/src/homeassistant/homeassistant/loader.py", line 674, in _import_platform
return importlib.import_module(f"{self.pkg_path}.{platform_name}")
File "/usr/local/lib/python3.10/importlib/__init__.py", line 126, in import_module
return _bootstrap._gcd_import(name[level:], package, level)
File "<frozen importlib._bootstrap>", line 1050, in _gcd_import
File "<frozen importlib._bootstrap>", line 1027, in _find_and_load
File "<frozen importlib._bootstrap>", line 1006, in _find_and_load_unlocked
File "<frozen importlib._bootstrap>", line 688, in _load_unlocked
File "<frozen importlib._bootstrap_external>", line 879, in exec_module
File "<frozen importlib._bootstrap_external>", line 1017, in get_code
File "<frozen importlib._bootstrap_external>", line 947, in source_to_code
File "<frozen importlib._bootstrap>", line 241, in _call_with_frames_removed
File "/config/custom_components/clear_grass/sensor.py", line 20
"""Container of air quality monitor status."""
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
IndentationError: expected an indented block after class definition on line 19
2022-08-14 17:32:17.851 ERROR (MainThread) [homeassistant.config] Platform error: sensor
Traceback (most recent call last):
File "/usr/src/homeassistant/homeassistant/loader.py", line 657, in get_platform
cache[full_name] = self._import_platform(platform_name)
File "/usr/src/homeassistant/homeassistant/loader.py", line 674, in _import_platform
return importlib.import_module(f"{self.pkg_path}.{platform_name}")
File "/usr/local/lib/python3.10/importlib/__init__.py", line 126, in import_module
return _bootstrap._gcd_import(name[level:], package, level)
File "<frozen importlib._bootstrap>", line 1050, in _gcd_import
File "<frozen importlib._bootstrap>", line 1027, in _find_and_load
File "<frozen importlib._bootstrap>", line 1006, in _find_and_load_unlocked
File "<frozen importlib._bootstrap>", line 688, in _load_unlocked
File "<frozen importlib._bootstrap_external>", line 879, in exec_module
File "<frozen importlib._bootstrap_external>", line 1017, in get_code
File "<frozen importlib._bootstrap_external>", line 947, in source_to_code
File "<frozen importlib._bootstrap>", line 241, in _call_with_frames_removed
File "/config/custom_components/clear_grass/sensor.py", line 20
"""Container of air quality monitor status."""
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
IndentationError: expected an indented block after class definition on line 19
The above exception was the direct cause of the following exception:
Traceback (most recent call last):
File "/usr/src/homeassistant/homeassistant/config.py", line 878, in async_process_component_config
platform = p_integration.get_platform(domain)
File "/usr/src/homeassistant/homeassistant/loader.py", line 666, in get_platform
raise ImportError(
ImportError: Exception importing custom_components.clear_grass.sensor
Everything works for me without errors. Try deleting all rows with battery from sensor.ru
Everything works for me without errors. Try deleting all rows with battery from sensor.ru
I just copy/pasted your code into sensor. I think that when you pasted the code into a comment - something lost in the file. As I already said - it is strangely formatted. Could you paste a code on some other external resource? (pastebin,...)
I tried to compare your code with an original one - and got a lot of differences on indentation.
If the HA version is 2022.8.4, then in the manifest file you need to change the version to "python-miio>=0.5.12"
@akarpych Yes! Exactly what I meant - loosing indentation when pasting into a comment. Here is a comparison of YOUR version & author's fixed version: https://www.diffchecker.com/w80ShahZ
Basic differences are:
Pasted your code into my file, rebooted - and no errors in Log, no ClearGrass sensor is created.
If the HA version is 2022.8.4, then in the manifest file you need to change the version to "python-miio>=0.5.12"
Running HA 2022.8.3. Took a manifest file from the author's fixed version. Rebooted - same: no errors in Log, no ClearGrass sensor is created.
Try to upgrade
Try to upgrade
If you mean "upgrade HA to 2022.8.4" - it did not help. Let's check if I did right:
Here is how sensor is declared:
sensor:
- platform: clear_grass
name: xxxxxxxxxxxxxxx
host: 192.168.x.x
token: some token
@ildar170975 HA 2022.8.4. I updated manifest (python-miio>=0.5.12) and copy/paste the code from @akarpych comment to sensor.py. Everything is ok - a new sensor has appeared
1) check the token (it may have changed) 2) check the way to add a new sensor - if the path to the folder with sensors is specified in the configuration, then the first line (sensors: ...) in the new file does not need to be specified 3) ... well, I hope there are no dublicate sensors names )
- check the token (it may have changed)
You are absolutely right! Tokens were changed since I reset devices to reconnect them to MiHome! After firmware update, MiHome was unable to connect to ClearGrass devices, so I reset monitors and reconnected them to MiHome. BTW, a battery_level is still available in MiHome.
So, after updating tokens in HA my monitors work again! @akarpych, @Leon-1409 - thanks a lot.
So, now we are waiting for restoring the old functionality...
Try to upgrade
If you mean "upgrade HA to 2022.8.4" - it did not help. Let's check if I did right:
- Copy / paste you code into sensor.py.
- Copy /paste manifest from here.
Here is how sensor is declared:
sensor: - platform: clear_grass name: xxxxxxxxxxxxxxx host: 192.168.x.x token: some token
Hi @ildar170975 can you please guide me as to where to access the sensor.py file and where and how do you copy the manifest.
can you please guide me as to where to access the sensor.py file and where and how do you copy the manifest.
@batja84 thanks for that. All up and running now.
Hello! I am newbie. Help me to understand. I downloaded the archive and put it in custom_components. Also announced in sensor:
But doesn't work....
updated to 8.6 the problem remained. You can paint step by step what to do, it doesn’t work out. Thank you in advance for your help
2022-08-19 12:20:44.706 ERROR (SyncWorker_3) [custom_components.clear_grass.sensor] Count (7) of requested properties does not match the count (2) of received values. 2022-08-19 12:20:44.867 ERROR (MainThread) [custom_components.clear_grass.sensor] Got exception while fetching the state: dictionary update sequence element #0 has length 1; 2 is required 2022-08-19 12:20:53.220 ERROR (MainThread) [homeassistant.helpers.event] Error while processing template: Template("{{ (states('sensor.termogolovka_komnata_position')| int == 100) }}")
temperature: 25.7 humidity: 46.2 co2: 1226 tvoc: 316 battery_state: charging model: cgllc.airmonitor.s1 unit_of_measurement: AQI icon: mdi:cloud friendly_name: Xiaomi ClearGrass Air Detector
figured out deleted the battery status, still does not show pm2.5
temperature: 25.7 humidity: 46.2 co2: 1226 tvoc: 316 battery_state: charging model: cgllc.airmonitor.s1 unit_of_measurement: AQI icon: mdi:cloud friendly_name: Xiaomi ClearGrass Air Detector
figured out deleted the battery status, still does not show pm2.5
uncomment
Thanks, got it working
Confirm, it's working
Hello, there is a easy way to get ClearGrass working in HA - via HACS integration Xiaomi Miot Auto. P.
or direct way to connect to your MQTT server https://touch-max.ru/umnyj-dom/otvyazka-clear-grass-air-monitor-ot-oblaka-i-podklyuchenie-k-home-assistant
Cleaned up the "sensor.py" file:
battery_level
: if value is not a dict - use "100" value.https://github.com/ildar170975/cleargrass_ha/blob/main/sensor.py
So far have not found a way to retrieve battery_level
data.
Meanwhile using a fixed "100" value.
@Cheaterdev If you have some spare time - please have a look at my changed file; you are more than welcome to replace the old file with this new one.
After updating a ClearGrass Air Monitor to 4.1.8_0244 the device is not available in HA. It is still available in MiHome.