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

Filter out value 1 from the property AQI #925

Closed
bieniu opened this issue Feb 1, 2021 · 12 comments · Fixed by #930
Closed

Filter out value 1 from the property AQI #925

bieniu opened this issue Feb 1, 2021 · 12 comments · Fixed by #930

Comments

@bieniu
Copy link
Contributor

bieniu commented Feb 1, 2021

Is your feature request related to a problem? Please describe.
Currently, the value of the AQI attribute of air purifier in Home Assistant is sometimes set to 1 for a short period of time. The device display never shows these values.

air_purifier

Describe the solution you'd like
python-miio should filter out values <=1 from aqi property.

Device information:
If the enhancement is device-specific, please include also the following information.

  • Name(s) of the device: Xiaomi Mi Air Purifier 3H
  • Link:

Use miiocli device --ip <ip address> --token <token>.

  • Model: zhimi.airpurifier.mb3
  • Hardware version: esp32
  • Firmware version: 2.1.8

Additional context
Add any other context or screenshots about the feature request here.

@syssi
Copy link
Collaborator

syssi commented Feb 1, 2021

Could you increase the log level and provide some traffic? Does the device response contain aqi: 1 sometimes?

logger:
  default: warn
  logs:
    homeassistant.components.xiaomi_miio: debug
    miio: debug

@bieniu
Copy link
Contributor Author

bieniu commented Feb 1, 2021

Sure, I'll provide the log.

@syssi
Copy link
Collaborator

syssi commented Feb 1, 2021

In the mean time you could pipe the measurements through the statistics component:

https://www.home-assistant.io/integrations/statistics/

@bieniu
Copy link
Contributor Author

bieniu commented Feb 1, 2021

That's exactly what I do 😁

@bieniu
Copy link
Contributor Author

bieniu commented Feb 1, 2021

I can confirm, the device sends value 1 for aqi.

2021-02-01 12:22:08 DEBUG (SyncWorker_4) [miio.miioprotocol] miairpurifier.bieniu.lan:54321 (ts: 1970-01-02 13:26:43, id: 402) << {'id': 402, 'result': [{'did': 'power', 'siid': 2, 'piid': 2, 'code': 0, 'value': False}, {'did': 'fan_level', 'siid': 2, 'piid': 4, 'code': 0, 'value': 1}, {'did': 'mode', 'siid': 2, 'piid': 5, 'code': 0, 'value': 3}, {'did': 'humidity', 'siid': 3, 'piid': 7, 'code': 0, 'value': 32}, {'did': 'temperature', 'siid': 3, 'piid': 8, 'code': 0, 'value': 22.1}, {'did': 'aqi', 'siid': 3, 'piid': 6, 'code': 0, 'value': 30}, {'did': 'filter_life_remaining', 'siid': 4, 'piid': 3, 'code': 0, 'value': 99}, {'did': 'filter_hours_used', 'siid': 4, 'piid': 5, 'code': 0, 'value': 15}, {'did': 'buzzer', 'siid': 5, 'piid': 1, 'code': 0, 'value': False}, {'did': 'buzzer_volume', 'siid': 5, 'piid': 2, 'code': -4001}, {'did': 'led_brightness', 'siid': 6, 'piid': 1, 'code': 0, 'value': 0}, {'did': 'led', 'siid': 6, 'piid': 6, 'code': 0, 'value': True}, {'did': 'child_lock', 'siid': 7, 'piid': 1, 'code': 0, 'value': False}, {'did': 'favorite_level', 'siid': 10, 'piid': 10, 'code': 0, 'value': 14}, {'did': 'favorite_rpm', 'siid': 10, 'piid': 7, 'code': 0, 'value': 2150}], 'exe_time': 340}
2021-02-01 12:22:38 DEBUG (SyncWorker_2) [miio.miioprotocol] miairpurifier.bieniu.lan:54321 (ts: 1970-01-02 13:27:13, id: 404) << {'id': 404, 'result': [{'did': 'power', 'siid': 2, 'piid': 2, 'code': 0, 'value': False}, {'did': 'fan_level', 'siid': 2, 'piid': 4, 'code': 0, 'value': 1}, {'did': 'mode', 'siid': 2, 'piid': 5, 'code': 0, 'value': 3}, {'did': 'humidity', 'siid': 3, 'piid': 7, 'code': 0, 'value': 32}, {'did': 'temperature', 'siid': 3, 'piid': 8, 'code': 0, 'value': 22.1}, {'did': 'aqi', 'siid': 3, 'piid': 6, 'code': 0, 'value': 1}, {'did': 'filter_life_remaining', 'siid': 4, 'piid': 3, 'code': 0, 'value': 99}, {'did': 'filter_hours_used', 'siid': 4, 'piid': 5, 'code': 0, 'value': 15}, {'did': 'buzzer', 'siid': 5, 'piid': 1, 'code': 0, 'value': False}, {'did': 'buzzer_volume', 'siid': 5, 'piid': 2, 'code': -4001}, {'did': 'led_brightness', 'siid': 6, 'piid': 1, 'code': 0, 'value': 0}, {'did': 'led', 'siid': 6, 'piid': 6, 'code': 0, 'value': True}, {'did': 'child_lock', 'siid': 7, 'piid': 1, 'code': 0, 'value': False}, {'did': 'favorite_level', 'siid': 10, 'piid': 10, 'code': 0, 'value': 14}, {'did': 'favorite_rpm', 'siid': 10, 'piid': 7, 'code': 0, 'value': 2150}], 'exe_time': 210}
2021-02-01 12:23:08 DEBUG (SyncWorker_3) [miio.miioprotocol] miairpurifier.bieniu.lan:54321 (ts: 1970-01-02 13:27:43, id: 406) << {'id': 406, 'result': [{'did': 'power', 'siid': 2, 'piid': 2, 'code': 0, 'value': False}, {'did': 'fan_level', 'siid': 2, 'piid': 4, 'code': 0, 'value': 1}, {'did': 'mode', 'siid': 2, 'piid': 5, 'code': 0, 'value': 3}, {'did': 'humidity', 'siid': 3, 'piid': 7, 'code': 0, 'value': 32}, {'did': 'temperature', 'siid': 3, 'piid': 8, 'code': 0, 'value': 22.1}, {'did': 'aqi', 'siid': 3, 'piid': 6, 'code': 0, 'value': 30}, {'did': 'filter_life_remaining', 'siid': 4, 'piid': 3, 'code': 0, 'value': 99}, {'did': 'filter_hours_used', 'siid': 4, 'piid': 5, 'code': 0, 'value': 15}, {'did': 'buzzer', 'siid': 5, 'piid': 1, 'code': 0, 'value': False}, {'did': 'buzzer_volume', 'siid': 5, 'piid': 2, 'code': -4001}, {'did': 'led_brightness', 'siid': 6, 'piid': 1, 'code': 0, 'value': 0}, {'did': 'led', 'siid': 6, 'piid': 6, 'code': 0, 'value': True}, {'did': 'child_lock', 'siid': 7, 'piid': 1, 'code': 0, 'value': False}, {'did': 'favorite_level', 'siid': 10, 'piid': 10, 'code': 0, 'value': 14}, {'did': 'favorite_rpm', 'siid': 10, 'piid': 7, 'code': 0, 'value': 2150}], 'exe_time': 170}

@bieniu
Copy link
Contributor Author

bieniu commented Feb 1, 2021

So maybe we can change this into this:

    @property
    def aqi(self) -> int:
        """Air quality index."""
        return max(self.data["aqi"], 2)

@syssi
Copy link
Collaborator

syssi commented Feb 1, 2021

Hmm.. so the lower bound of the measurements would be 2 always.

@bieniu
Copy link
Contributor Author

bieniu commented Feb 1, 2021

Yup. Do you have a better solution?

@syssi
Copy link
Collaborator

syssi commented Feb 1, 2021

You could remember the last value(s). If it the previous value is near to 1 a AQI of 1 is a valid value. If the previous value is pretty high a AQI of 1 should be dropped / or the previous value should be reported again.

@rytilahti
Copy link
Owner

Maybe AQI = 1 is just in-band signaling for "unable to measure"? In that case, returning None would be the correct way (to let the downstreams also know that the measurement failed) instead of having a cache (which can be implemented by the downstream users themselves.

@bieniu
Copy link
Contributor Author

bieniu commented Feb 2, 2021

If the previous value is pretty high a AQI of 1 should be dropped

So we can use somethig like this:

@property
def aqi(self) -> int:
    """Air quality index."""
    if not self._last_aqi_value:
        self._last_aqi_value = self.data["aqi"]
        return self.data["aqi"]

    if (
        self.data["aqi"] == 1
        and self._last_aqi_value != 0
        and (self._last_aqi_value - self.data["aqi"]) / self._last_aqi_value > 0.9
    ):
        return self._last_aqi_value

    self._last_aqi_value = self.data["aqi"]
    return self.data["aqi"]

Maybe AQI = 1 is just in-band signaling for "unable to measure"?

Can we check somewhere if this assumption is true?

@rytilahti
Copy link
Owner

Can we check somewhere if this assumption is true?

Not really, but assuming the app is not showing that (i.e., it considers it as invalid) and it is always exactly 1 on those cases, then it's a reasonable assumption.

In my opinion the library should be returning None for those to give the downstreams a chance to interpret it as they want to (instead of using a cached value, which may be even very old depending on how often one does updates).

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging a pull request may close this issue.

3 participants