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

New thermostat tile for Wear OS #4959

Open
wants to merge 26 commits into
base: master
Choose a base branch
from

Conversation

Martreides
Copy link

Summary

This pull request is intended to add a thermostat tile to the Wear OS app. It shows the target and current temperature, and allows a user to change the target temperature. The high level set up of the implementation is based on the existing tiles, mostly the camera tile.

Screenshots

Screenshot_20250105_174129_One UI Watch Home

Link to pull request in Documentation repository

Documentation: home-assistant/companion.home-assistant#1155

Any other notes

This is my first contribution to an Android project. A good review of the PR is appreciated.

Copy link

@home-assistant home-assistant bot left a comment

Choose a reason for hiding this comment

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

Hi @Martreides

It seems you haven't yet signed a CLA. Please do so here.

Once you do that we will be able to review and accept this pull request.

Thanks!

@Martreides Martreides changed the title Develop thermostat tile New thermostat tile for Wear OS Jan 5, 2025
@jpelgrom
Copy link
Member

jpelgrom commented Jan 6, 2025

Here's a tip: running ./gradlew ktlintFormat locally will fix most of the errors the linter is giving you automatically (see project README file).

Don't forget to mark the PR as ready to review when you're done.

@Martreides
Copy link
Author

Thanks for the tip! Before my last commit I had one issue left, which should be fixed in my latest commit. Good to know for future commits though!

@Martreides Martreides marked this pull request as ready for review January 6, 2025 13:03
@dshokouhi
Copy link
Member

So just a thought but maybe we should call this a Climate Tile instead of Thermostat tile to be more precise? Users can add any climate entity but does not specifically need to be a thermostat?


serverManager.integrationRepository().callAction(
entityStr.split(".")[0],
"set_temperature",
Copy link
Member

Choose a reason for hiding this comment

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

Looks like we need to do a state check to prevent a possible error?

https://www.home-assistant.io/integrations/climate/#action-climateset_temperature

New target temperature for climate device (commonly referred to as a setpoint). Do not use if hvac_mode is heat_cool.

Copy link
Author

Choose a reason for hiding this comment

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

Good point, I wasn't aware of that. I will add a state check later today to handle that. Any best practice on what to do if that hvac_mode is heat_cool? From the docs I understand that in that case both target_temp_high and target_temp_low should be provided, but that is not supported by the tile currently.

Copy link
Member

Choose a reason for hiding this comment

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

Hmm might be best to skip that state for now 🤔 and maybe just hide controls? Dont think it makes sense at all to set both low and high to the same value right?

Copy link
Author

Choose a reason for hiding this comment

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

I don't have any device myself that has a high and low. But, I can imagine that it might not be good to set those to the same value. I guess it would always be either cooling or heating because it's never between the min and max 😅.

@Martreides
Copy link
Author

That's something I have been thinking about as well. In the end I went with Thermostat Tile since it only functions as a thermostat. The docs write that climate entities can "control temperature, humidity, or fans, such as A/C systems and humidifiers." Since this tile only controls temperature and nothing else I was afraid that Climate Tile might be too broad. One reason I can think of for going with Climate Tile is to accommodate future additions.

Note that in the code I did try to be clear that the entity being used is the climate entity.

@dshokouhi
Copy link
Member

Thanks for clarifying it does make sense in the current use case however one thing to consider is that later on changing the name may lead to a breaking change as the tile path is in the manifest. Changing that later may have the undesired effect of removing the tile as the path can no longer be referenced.

With that said I can see that multiple tiles are allowed to be added for this tile. Maybe we should consider showing the entity friendly name or icon to help distinguish between multiple tiles? Also did you consider showing the state? Might be helpful to know if the thermostat is on for example?

Thanks for the PR as well 🙏 , looks like this will let us close #2555 based on current functionality.

@dshokouhi
Copy link
Member

@Martreides
Copy link
Author

Looks like we also need to check if the climate entity supports changing the temp

I guess we can combine your earlier comment into this as well right? We do one check to determine whether the entity can be controlled by this tile and use that throughout the code. I will have to dive into this for a bit. I see my own climate entity reports as 385, which is target_temperature, turn_off and turn_on. Since the ClimateControl code that implements this is part of the phone app I guess we cannot use any part of it directly right?

Maybe we should consider showing the entity friendly name or icon to help distinguish between multiple tiles?

I don´t entirely follow what you mean here. Do you mean to show the name or icon on the tile?

Also did you consider showing the state?

Ideally I would like to show it the same as in the browser, it shows the state and glows if heating. The glowing is a bit too complicated for me at this point, but I think the state should be quite easy to add.

looks like this will let us close #2555

Nice, I wasn't aware that issue existed!

@dshokouhi
Copy link
Member

I guess we can combine your earlier comment into this as well right? We do one check to determine whether the entity can be controlled by this tile and use that throughout the code.

Yup that sounds like a good approach

I will have to dive into this for a bit. I see my own climate entity reports as 385, which is target_temperature, turn_off and turn_on. Since the ClimateControl code that implements this is part of the phone app I guess we cannot use any part of it directly right?

So not directly but you can move some of that logic to our Entity extensions and then reuse that elsewhere. Helps keep all that business logic in one place to easily reference :)

I don´t entirely follow what you mean here. Do you mean to show the name or icon on the tile?

Yes something to help differentiate between multiple tiles being added otherwise its a guessing game :) Imagine a user adding a tile for upstairs and downstairs thermostats how do they tell them apart quickly

Ideally I would like to show it the same as in the browser, it shows the state and glows if heating. The glowing is a bit too complicated for me at this point, but I think the state should be quite easy to add.

Hmm maybe instead of glow we match the frontend color? They seem to use orange for heat, blue for cool and white for idle/off. We typically try to match frontend behavior to help meet user expectations

image

image

image

…ing) based on which the font changes color. Also includes the friendly name of the entity at the op.
@Martreides
Copy link
Author

Martreides commented Jan 6, 2025

The last commits contains changes to the layout of the tile. It now shows the friendly name of the entity at the top. I'm not completely sure on whether each entity has a friendly name though. It also shows the state of the entity (Idle, Heating or Cooling), based on the state the color of the state and the actual temperature changes (this reflects the behaviour of the card).

I think it would be nice as well if we add the unit (C or F) to the tile. However, I am struggling with figuring out how to determine whether to use C or F. In the docs I do see a required field temperature_unit, but at least my climate entity does not have it.

Screenshot_20250106_224748
Screenshot_20250106_224736

Edit: also changed the colour of the buttons to use the color from the HA theme.

@dshokouhi
Copy link
Member

dshokouhi commented Jan 6, 2025

Latest screenshot looks great! Does make you wonder how closely the tile should try to match the frontend here. Hard to consider things here too because we cant scroll so we have limited space

The last commits contains changes to the layout of the tile. It now shows the friendly name of the entity at the top. I'm not completely sure on whether each entity has a friendly name though.

We actually handle that by defaulting to entity ID if not provided

https://github.com/home-assistant/android/blob/master/common/src/main/java/io/homeassistant/companion/android/common/data/integration/Entity.kt#L791

I think it would be nice as well if we add the unit (C or F) to the tile. However, I am struggling with figuring out how to determine whether to use C or F. In the docs I do see a required field temperature_unit, but at least my climate entity does not have it.

hmm mine does not either, maybe for the unit it could be best to go by the config response because on my end i have no control over the unit like we can with sensors

https://github.com/home-assistant/android/blob/master/common/src/main/java/io/homeassistant/companion/android/common/data/websocket/impl/entities/GetConfigResponse.kt#L10

@Martreides
Copy link
Author

Does make you wonder how closely the tile should try to match the frontend here. Hard to consider things here too because we cant scroll so we have limited space

Indeed! I think this looks good, but we should not make it more crowded.

We actually handle that by defaulting to entity ID if not provided

Great! I am thinking about adding a setting so users can choose whether to show the name. Myself I would prefer it without as I only have a single climate entity. That should be quite easy to add though.

hmm mine does not either, maybe for the unit it could be best to go by the config response because on my end i have no control over the unit like we can with sensors

Thanks! Will have a look at that and the other changes tomorrow evening.

@dshokouhi
Copy link
Member

but we should not make it more crowded.

I agree however I cannot escape the thought of users asking about controlling the state too 🙈 . For this PR not necessary as the MVP solves a good use case, but in the future we can consider a button to toggle through the states just like we do with device controls. Mentioning this here so others can see we discussed it. Given the state of the app its not required for this tile as users can still get by using scripts and such on the watch for state control

Should we consider updating the UI to match the frontend when the device is off? State control seems to only be allowed when it is off so not sure if its ok to send the set temp action when it is off.

Side note: we can probably adapt the changes here for other domains like media player, number etc... for additional tiles in the future :) Great work!!

@Martreides
Copy link
Author

Martreides commented Jan 7, 2025

Should we consider updating the UI to match the frontend when the device is off? State control seems to only be allowed when it is off so not sure if its ok to send the set temp action when it is off.

I'm thinking about showing "--.-" instead of the target temperature, keep the current temperature and hide the "+" and "-" button. That should align quite well to what we have in the card. Currently I do this by checking whether the hvacAction == "Off". However, my climate entity does not really have an off state so I can't test that. Do you have an idea whether this should work?

but in the future we can consider a button to toggle through the states just like we do with device controls

It would be nice to show the action (cooling or heating) by coloring the edge of the tile. That should be doable and will free up some room on the tile. I will leave that as nice to have for now though.

hmm mine does not either, maybe for the unit it could be best to go by the config response because on my end i have no control over the unit like we can with sensors

Btw, this works!

Edit: I manually changed the state of my climate entity
Screenshot_20250107_200937

@Martreides
Copy link
Author

It ended up being a bit more difficult than I expected, but I have the toggle for showing the friendly name of the entity in😄.
Screenshot_20250107_223758

SwitchButton(
modifier = Modifier.fillMaxWidth(),
checked = tile?.showEntityName == true,
onCheckedChange = {
Copy link
Author

@Martreides Martreides Jan 7, 2025

Choose a reason for hiding this comment

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

@dshokouhi, could you have a look at how I ended up handling the callback? I had some issues here because the callback only accepts functions with just a Boolean parameter. To work around that I ended up doing it this way.

Edit: I'm referring to the callback when clicking the "show name" toggle.

@Martreides
Copy link
Author

Martreides commented Jan 8, 2025

How do you like these? In my opinion these are a bit cleaner than changing the colour of the text.
Screenshot_20250108_201113_One UI Watch Home
Screenshot_20250108_200848_analogmodular
Screenshot_20250108_201540_One UI Watch Home
Screenshot_20250108_202511_One UI Watch Home

Copy link
Member

@jpelgrom jpelgrom left a comment

Choose a reason for hiding this comment

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

thermostat_tile_example.png

This should be a realistic preview of the tile like in your last comment (but maybe without the title so we don't have to deal with localizing the image).

@Martreides
Copy link
Author

@jpelgrom, what is the best practice on resolving your review comments? I have some other changes pending as well on the layout of the tile. Should I make specific commits per review comments or can I combine them together? First time working on a project like this :) .

@jpelgrom
Copy link
Member

jpelgrom commented Jan 8, 2025

You can use individual commits or one big commit for all review comments, personal preference. Just don't push other unrelated changes in the same commit, or rewrite commit history, so it is easy to check changes for review.

val hvacActionColor = when (hvacAction) {
"Heating" -> getColor(R.color.colorDeviceControlsThermostatHeat)
"Cooling" -> getColor(R.color.colorDeviceControlsDefaultOn)
else -> 0x00000000
Copy link
Member

Choose a reason for hiding this comment

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

Also use a color here (android.R.color.black)

Copy link
Author

@Martreides Martreides Jan 8, 2025

Choose a reason for hiding this comment

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

This is only intended to make the outer ring fully transparent if the hvac_action is not heating or cooling. Initially hvacActionColor was also used for text, but as you can see in my last screenshots that is no longer the case.

@Martreides
Copy link
Author

Thanks a lot for the thorough review! I have responded to all of the individual comments. Let me know if you have any follow-up or additional feedback!

At the current stage I am quite happy with how the tile looks and functions. If I have time tomorrow I would like to do some test on emulated devices with different screens (sizes and shapes).

@jpelgrom
Copy link
Member

jpelgrom commented Jan 9, 2025

Could you put the example tile image in tinypng.com and update it? Should be able to get it smaller, not a lot of color so probably compresses nicely without too much artifacts.

@Martreides
Copy link
Author

Could you put the example tile image in tinypng.com and update it? Should be able to get it smaller, not a lot of color so probably compresses nicely without too much artifacts.

63% saved 😄

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

Successfully merging this pull request may close these issues.

3 participants