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

Support for the PUREi9 Robot Vacuum #145

Merged
merged 7 commits into from
Sep 25, 2024
Merged

Conversation

joakimjalden
Copy link
Contributor

In case you wish to not only support the line of air purifiers, I added basic support for the PUREi9.2 robot vacuum. I've been testing the code in a HA developer environment, and about a day in my production setup. It supports start, stop, pause, and return_to_base, along with battery status. The added functionality was (at least for me) mostly to get around the fac that "Home Assistant Pure i9", which builds on the purei9_unofficial python API, has been broken since August when Electrolux made changes to their API authorization.

I was not completely sure of how to best pass on the battery state to the vacuum entity (rather than as a separate sensor) so I passed it with the application object I believe similar to how the the WorkMode of the air purifier fans is implemented, but it requires a bunch of special cases as the data object for the robot vacuum is a bit different that that of the air purifiers (e.g., no Workmode key). The vaccum.py class may also be a bit to hard coded. It was a bit hard to decide where to draw the line between the platform and functionality provided by api.py.

Next in line for implementation in my system is the fan mode (powerMode) setting (a skeleton if there but disabled because I was unsure of the formatting of the payload to send to the Wellbeing API), as well as support for sending the vacuum to a specific location.

Copy link
Owner

@JohNan JohNan left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thank you, It's a great start!

I would like to move the battery state and fan speed constants to properties on the Appliance because I guess they can have different values depending on the model. Something similar to speed_range where we switch based on model.

I'm also thinking if it would be a good idea to subclass Appliance into VacuumAppliance and PurifierAppliance to keep appliance specific properties separated. But that can be refactored at some other time if needed.

@derkrasseleo
Copy link

Works with my AEG Pure i9, great work!

Comment on lines 53 to 61
BATTERY_LEVELS = {
0: 0,
1: 10,
2: 30,
3: 50,
4: 70,
5: 90,
6: 100,
}
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Make a property of this in Appliance

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done. Copied the implementation of speed range and similarly used ranged_value_to_percentage, except that range value 1 has to be excluded to make the lower battery state 0%. Note that there was a bug in the prior implementation because the lowest value that the battery state can take is 1 and not 0, as I previously thought.

Comment on lines 74 to 78
FAN_SPEEDS = {
1: "Quiet",
2: "Smart",
3: "Power",
}
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Make a property of this in Appliance

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done. Check if it is ok to define the list in the property function rather than elsewhere (e.g., in the const file).

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The specific set of values probably needs to be looked at before enabling the FAN_SPEED to ensure compatibility with both the original purei9 and the purei9.2.

Comment on lines +314 to +319
if "Workmode" in data:
self.mode = WorkMode(data.get("Workmode"))
if "powerMode" in data:
self.power_mode = data.get("powerMode")
if "batteryStatus" in data:
self.battery_status = data.get("batteryStatus")
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can this be decided depending on model? Not sure if it can mean different things depending on the model.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes. I do not see why not. Do you mean models of vacuums of different device_types?

Looking at the purei9_unofficial code (capabilities2model, row 118 in common.py), it seems that "powerMode" is just for the purei9.2 while the older (AEG?) purei9 has an "ecomode" instead. I do not know about the batterStatus but maybe @derkrasseleo can chime in if he knows.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I have not done any code changes in the last update for this.

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes. I do not see why not. Do you mean models of vacuums of different device_types?

Looking at the purei9_unofficial code (capabilities2model, row 118 in common.py), it seems that "powerMode" is just for the purei9.2 while the older (AEG?) purei9 has an "ecomode" instead. I do not know about the batterStatus but maybe @derkrasseleo can chime in if he knows.

My AEG pure i9 has Quiet, Smart and Power mode

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Just to clarify: it's actually a AEG RX9.2 so probably more similar to the Pure i9.2

@joakimjalden
Copy link
Contributor Author

I'm a bit new to contributing to open-source projects. This PR was my first ever. Is it sufficient to push the requested changes to the branch in my fork or do I need to make a new PR?

@joakimjalden
Copy link
Contributor Author

One more thing for today. For actually enabling the FAN_SPEED feature, and allowing HA to set the vacuum fan speed, it seems that the json payload was correct after all, but it should be sent to f"appliances/{self.id}" rather than f"appliances/{self.id}/command", which I believe requires adding a new function to pyelectroluxgroup. I have to test that this works to be sure, but should I make such a suggestion as a PR to that repo or is it sufficient to to make it as a suggestion here?

@HonkStonk
Copy link

HonkStonk commented Sep 24, 2024

Wonderful work here! I sifted through the changes and comments here - looks great and makes me eager to make a try to for the first time test code not through HACS in HA :)

I have 2x Pure i9.2's to test on. That I love and need. Had them since development of them started (worked in the same area but not with them specifically).

Wish I had more time to contribute but all I can say for now is that the AEG and Electrolux variants are just rebrandings on the box and some namings. Diff between 9 and 9.2 should not be so big either. From what I remember this series has always just had three power level modes in total - all models.

The only model difference I recall when it comes to robot firmware is that they have different capacity battery packs which just affects the return to home point. But that should not make a difference when externally accessed.

For the battery levels - isn't the resolution kind of "low, mid, high"?
And the dustbin full sensor is just a 3h runtime timer.,.. :)

Keep up the great work and thank you!

@joakimjalden
Copy link
Contributor Author

Wonderful work here! I sifted through the changes and comments here - looks great and makes me eager to make a try to for the first time test code not through HACS in HA :)

If I figure out the code review process, you may not have to :)

I have 2x Pure i9.2's to test on. That I love and need.

Same here.

Wish I had more time to contribute but all I can say for now is that the AEG and Electrolux variants are just rebrandings on the box and some namings. Diff between 9 and 9.2 should not be so big either. From what I remember this series has always just had three power level modes in total - all models.

Good to know.

For the battery levels - isn't the resolution kind of "low, mid, high"? And the dustbin full sensor is just a 3h runtime timer.,.. :)

The battery in the Electrolux app shows as "log, mid, high, full," but my reading from the HA developer docs was that battery_level should be of type int, which is why I translated it. The vacuum just returns a value between 1 (empty) and 6 (full) in the API.

Keep up the great work and thank you!
Thank you.

@derkrasseleo
Copy link

Only thing that's missing for me is vacuum.send_command to tell the vacuum to only clean certain zones, which doesn't seem to work yet. Is it possible to implement this?

Copy link
Owner

@JohNan JohNan left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Improvements can always be made as new PRs. I think this is a good start, so let's go! @joakimjalden if I have a green light from you I can merge and create a new release.

@JohNan JohNan linked an issue Sep 25, 2024 that may be closed by this pull request
@blavak68
Copy link

hello boys

First of all, I want to thank you for a great job

I have one tip about what was good about the previous integration...
was it possible to send a vacuum cleaner to specific zones, can you try to look at it?
two parameters were used for this, namely "map" and "zones"

https://github.com/Ekman/home-assistant-pure-i9/blob/1.5.0/MANUAL.md#additional-commands

thx

@joakimjalden
Copy link
Contributor Author

@joakimjalden if I have a green light from you I can merge and create a new release.

Absolutely. Go ahead. Let me know if I need to klick anything on GitHub.

@JohNan
Copy link
Owner

JohNan commented Sep 25, 2024

hello boys

First of all, I want to thank you for a great job

I have one tip about what was good about the previous integration... was it possible to send a vacuum cleaner to specific zones, can you try to look at it? two parameters were used for this, namely "map" and "zones"

https://github.com/Ekman/home-assistant-pure-i9/blob/1.5.0/MANUAL.md#additional-commands

thx

Let's start with this PR to add basic functionality and we can look into adding more features later on.

@JohNan JohNan merged commit 5434f30 into JohNan:main Sep 25, 2024
2 checks passed
@joakimjalden
Copy link
Contributor Author

hello boys

First of all, I want to thank you for a great job

I have one tip about what was good about the previous integration... was it possible to send a vacuum cleaner to specific zones, can you try to look at it? two parameters were used for this, namely "map" and "zones"

https://github.com/Ekman/home-assistant-pure-i9/blob/1.5.0/MANUAL.md#additional-commands

thx

It is not possible in the current state of the code but it is definitely on the list of next steps. I had that implemented in my own copy of the home-assistant-pure-i9 HA integration before it was officially added there, so I have (sort of) written that code once before. It is not that complicated, with the possible caveat that the Wellbeing API changed around this, but I don't think that is the case. It may however require additions to the python wrapper for the Wellbeing API that @JohNan wrote and which underlies this HA integration, which should also not be hard, but may require a few iterations. This said, due to my work situation, it will most likely have to wait until the weekend before I can contribute again.

@AndersRipa
Copy link

Fantastic work, I just installed (updated to the new version) it and was able to start my Pure i9 cleaner from Home Assistant!

@HonkStonk
Copy link

Tested late night through fresh install through HACS. I only tested one action/service (that I didn’t use/knew about before) - the ”Vacuum: Start” service that let me put both my robots as device targets. At first manual execution try (run action button inside the automation editor) it threw a ”Unknown error” at me. Clicked it again and both robots started as intended and have done so on both automatic and manual execution. So I just consider it a one-off fresh install glitch. Also return to home/pause works. And battery levels.

I noticed that my Ecovacs status is ”Docked” when on the charger and fully charged while the Pure i9’s show ”Idle” when fully charged on the charger. Don’t know if ”Charging” should also be a state or not in ”Status”.

Very nice job! Working great anyways!
Now I’m eager to look into the next steps if we get zone cleaning in (as others asked about) - never used it before but getting ideas about using it in an automation…

IMG_5588

@joakimjalden
Copy link
Contributor Author

joakimjalden commented Sep 26, 2024

@HonkStonk let us know if you experience the glitch again, especially if you find a way to force it or are able to catch any more information if it happens again. It may be some timing issue with the API calls or similar, and if so, maybe it can be dealt with.

For the docked versus idle state of the PUREi9, the vacuum reports idle (robotStatus: 14) through the Electrolux Wellbeing API when it has become fully charged, even if it is in the dock. The API can also report that it is charging (robotStatus: 9) which is now passed as "STATUS_DOCKED" to HA. Given the phrase "STATUS_DOCKED: The vacuum is currently docked, it is assumed that docked can also mean charging." in the HA developer documentation for vacuums I just translated robotStatus: 9 to STATUS_DOCKED and robotStatus: 14 to STATUS_IDLE, but I believe that the purei9_unofficial repo infers a docked (fully charged) state by reporting STAUS_DOCKED when the Wellbeing API is reporting robotState: 14 and the battery is full. This could be seen as more logical from the HA perspective, but has the negative consequence that if you remove a fully charged vacuum from the dock, it will still report STATUS_DOCKED. Edit: Maybe I am wrong here, because the battery drops pretty fast from batteryState: 6 to batteryState: 5 when removed from the dock, so overriding the state reported by the Wellbeing API may be the most logical thing to do after all.

Any feedback on what would be most logical and useful from the HA perspective is appreciated, and can be easily implemented. However, the Wellbeing API is for the PUREi9 does not include an indicator that explicitly means that the vacuum is physically in the dock.

My plan for Sunday is to try to implement the cleaning command that can send the robot to a specific zone. I am missing this functionality myself because I have an automation that send the robot to the kitchen when it has been used and we then leave the house :)

@joakimjalden
Copy link
Contributor Author

Don’t know if ”Charging” should also be a state or not in ”Status”.

The standard Vacuum entity class in HA does not have a "Charging" state, see documentation. I'm not sure if it ok (or wise) to add non-standard states to an integration, but I can look at what other (core) integrations in HA are doing here.

@HonkStonk
Copy link

@joakimjalden Will for sure look out for the Unknown error glitch again. Might well be timing related (also my HA had barely restarted when I tried it the first time). Not sure it's related but I often get that one of the two robots are unavailable from the cloud a few minutes here and there when I check their status (official app and HA)- I blame the cloud people :)

Thanks for pointing out the documentation! Hadn't checked it but now the states I see make sense. The end result still differs from my Ecovacs HA implementation though. As I interpret it with your implementation now for the Pure i9's I can interpret "Docked" as charging and "Idle" as fully charged (assuming my robots are never outside the charger while not cleaning). Might be useful if I wanted to run them again when they turn fully charged.

Ah - there are so many cases for zones I didn't experiment with... :)
One case is we come home and daughter pours 2 liters of sand from shoes in hall - that could be managed by sending the robot to the hallway. The other case is that it's time to empty the dustbin - then the robot should come out of its hidden cave (under freezer) and park near the big trash can.

@blavak68
Copy link

I know it's a detail, but wouldn't it be possible for the parameter "friendly_name:" to pull the name of the vacuum cleaner if it can give it to the name of the entity?
obrázok

@joakimjalden
Copy link
Contributor Author

@blavak68 That's a good suggestion. I'll look into it and, if possible, make another PR since this one has already been merged.

@joakimjalden
Copy link
Contributor Author

I have some bad news. I've been looking at the functionality of cleaning specific zones. Unfortunately, it seems that this capability is simply not exposed through the Electrolux developer API that this integration is using. I've sent an email to Electrolux for clarification to make sure it is just not something I have misunderstood. The "powerMode" (Fan speed setting) is the same story. Thus, before a possible response from Electrolux, there is not much I can do about either of these features. I will write here if I get a response from them.

@JohNan
Copy link
Owner

JohNan commented Sep 27, 2024

I have previously sent them an email about missing functionality for the air purifiers and got a response pretty quickly saying that they could add it. A few weeks later it was implemented. So I hope that they will be equally accommodating this time.

@jducamp
Copy link

jducamp commented Sep 30, 2024

Good afternoon,

Is there a way to make the difference in the vacuum states between what I would describe as:

  • the vacuum is idle doing nothing on its docking station
  • the vacuum is charging but the cleaning is complete
  • the vacuum is charging but the cleaning is not complete, hence it will resume once the battery is fully charged

Having dedicated status for each of those states would make it easier to design automation depending on the context of the home.

Thank you!

@HonkStonk
Copy link

HonkStonk commented Sep 30, 2024 via email

@jducamp
Copy link

jducamp commented Sep 30, 2024 via email

@joakimjalden
Copy link
Contributor Author

joakimjalden commented Sep 30, 2024

Good afternoon,

Same to you @jducamp. See #145 (comment) and the following post for general thoughts on this.

Is there a way to make the difference in the vacuum states between what I would describe as:

  • the vacuum is idle doing nothing on its docking station

This is not something that the Electrolux API is providing. Other HA integrations for the Pure i9 have inferred this from the combination of an idle state and full battery, but this has some other caveats as discussed above.

  • the vacuum is charging but the cleaning is complete

This (robotState 9) is what is now translated to STATE_DOCKED in the HA entity, and displays as "Docked" in the UI (with a small charging symbol next to the battery icon :).

  • the vacuum is charging but the cleaning is not complete, hence it will resume once the battery is fully charged

This (robotState 12) is explicitly reported by the Electrolux API and the only reason I did not pass it along as a unique state for the HA entity is that it did not fit one of the predefined states for the Vacuum entity class in HA. For me it was a question of opting for increased compatibility with HA by sticking to the predefined states for the entity class, or to provide improved expressiveness for the integration. I opted for compatibility, but am glad to take all of your feedback, and then especially from @JohNan as maintainer of the overall Wellbeing integration.

You can have a look at lines 34 to 47 of vacuum.py to see the full translation from states reported by the Electrolux API (the numbers 1 to 14) to HA states (the STATE_* statements, which are just string definitions). If you believe that the choices made could have been better and if you feel adventurous, you can always just change 12: STATE_DOCKED, on line 45 to 12: ”paused for charging and will continue cleaning…”, (or similar) on your local system if that is the state you want your vacuum to have in the case that it is charging to continue cleaning (which never happens for me since I have more battery than floor space :). Just note that I have not tested this thoroughly to make sure it plays nice with other parts of HA.

@joakimjalden
Copy link
Contributor Author

I have previously sent them an email about missing functionality for the air purifiers and got a response pretty quickly saying that they could add it. A few weeks later it was implemented. So I hope that they will be equally accommodating this time.

I also got a positive response today that they would add what they could but that some map-related parts may require other API functionalities that have not yet been released and may, therefore, take more time. I'm keeping my fingers crossed.

However, I also lost the ability to authorize with the API today, which is a bit worrying. I hope that was just because I went over the rate limit, and I will try again tomorrow.

@jducamp
Copy link

jducamp commented Sep 30, 2024

Alright now that's clear thank you, I might try your proposal and see if nothing collapse at home :)

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

Successfully merging this pull request may close these issues.

"Pure i9 is not a valid model"
7 participants