Open 8osman opened 5 years ago
+1 for this.. worked great previously on my system but sadly broken by latest climate changes in HA
I'm guessing Alex has been too busy to keep up with this.
I've had a go at making it work with the latest version of HA. I'm no programmer so it's probably a bit buggy.
One of the issues is setting PRESET_AWAY - it switches the unit to off, however I'm not using location sensing through warmup, so the unit then updates HA to say PRESET_HOME after a few seconds.
It doesn't switch the unit on again.
I'll probably fix this in future, but busy right now. I think it probably did this before as already in my automation it set preset away - then just auto for back on.
"""Platform that offers a connection to a warmup device."""
import logging
from typing import Optional, List
from homeassistant.components.climate import PLATFORM_SCHEMA, ClimateDevice
from homeassistant.components.climate.const import (
HVAC_MODE_AUTO,
HVAC_MODE_HEAT,
HVAC_MODE_OFF,
PRESET_AWAY,
PRESET_HOME,
SUPPORT_PRESET_MODE,
SUPPORT_TARGET_TEMPERATURE,
)
from homeassistant.const import (ATTR_TEMPERATURE, PRECISION_TENTHS, TEMP_CELSIUS, CONF_NAME, CONF_PASSWORD, CONF_USERNAME, CONF_ROOM)
from homeassistant.exceptions import PlatformNotReady
import homeassistant.helpers.config_validation as cv
from homeassistant.helpers.entity import async_generate_entity_id
from homeassistant.util.temperature import convert as convert_temperature
_LOGGER = logging.getLogger(__name__)
import voluptuous as vol
SUPPORT_FLAGS = SUPPORT_TARGET_TEMPERATURE | SUPPORT_PRESET_MODE
SUPPORT_HVAC_HEAT = [HVAC_MODE_HEAT, HVAC_MODE_AUTO, HVAC_MODE_OFF]
SUPPORT_PRESET = [PRESET_AWAY, PRESET_HOME]
CONF_LOCATION = 'location'
CONF_TARGET_TEMP = 'target_temp'
DEFAULT_NAME = 'warmup4ie'
DEFAULT_TARGET_TEMP = 20
PLATFORM_SCHEMA = PLATFORM_SCHEMA.extend({
vol.Optional(CONF_NAME, default=DEFAULT_NAME): cv.string,
vol.Required(CONF_USERNAME): cv.string,
vol.Required(CONF_PASSWORD): cv.string,
vol.Required(CONF_LOCATION): cv.string,
vol.Required(CONF_ROOM): cv.string,
vol.Optional(CONF_TARGET_TEMP,
default=DEFAULT_TARGET_TEMP): vol.Coerce(float),
})
def setup_platform(hass, config, add_entities, discovery_info=None):
"""Set up the Demo climate devices."""
_LOGGER.info("Setting up platform for Warmup component")
name = config.get(CONF_NAME)
user = config.get(CONF_USERNAME)
password = config.get(CONF_PASSWORD)
location = config.get(CONF_LOCATION)
room = config.get(CONF_ROOM)
target_temp = config.get(CONF_TARGET_TEMP)
from warmup4ie import Warmup4IEDevice
device = Warmup4IEDevice(user, password, location, room,
target_temp)
if device is None or not device.setup_finished:
raise PlatformNotReady
add_entities(
[Warmup(hass, name, device)])
class Warmup(ClimateDevice):
"""Representation of a Warmup device."""
mode_map = {'prog':HVAC_MODE_AUTO, 'fixed':HVAC_MODE_HEAT, 'off':HVAC_MODE_OFF}
def __init__(self, hass, name, device):
"""Initialize the climate device."""
_LOGGER.info("Setting up Warmup component")
self._name = name
self._hvac_mode = HVAC_MODE_AUTO
self._hvac_list = [HVAC_MODE_HEAT, HVAC_MODE_OFF, HVAC_MODE_AUTO]
self._unit_of_measurement = TEMP_CELSIUS
self._on = True
self._away_mode = False
self._device = device
self._support_flags = SUPPORT_FLAGS | SUPPORT_PRESET_MODE
self._awaymodeLastState = HVAC_MODE_OFF
@property
def supported_features(self):
"""Return the list of supported features."""
return SUPPORT_FLAGS
@property
def hvac_mode(self):
"""Return current HVAC mode."""
return self._hvac_mode
@property
def hvac_modes(self):
"""Return available HVAC modes."""
return self._hvac_list
@property
def should_poll(self):
"""Return the polling state."""
return True
@property
def name(self):
"""Return the name of the climate device."""
return self._name
@property
def temperature_unit(self):
"""Return the unit of measurement."""
return self._unit_of_measurement
@property
def current_temperature(self):
"""Return the current temperature."""
return self._device.get_current_temmperature()
@property
def target_temperature(self):
"""Return the temperature we try to reach."""
return self._device.get_target_temmperature()
@property
def min_temp(self):
"""Return the minimum temperature."""
return self._device.get_target_temperature_low()
@property
def max_temp(self):
"""Return the maximum temperature."""
return self._device.get_target_temperature_high()
@property
def preset_mode(self):
"""Return the current preset mode, e.g., home, away, temp."""
if self._away_mode:
return PRESET_AWAY
return PRESET_HOME
@property
def preset_modes(self):
"""Return a list of available preset modes."""
return [PRESET_HOME, PRESET_AWAY]
@property
def is_away_mode_on(self):
"""Return if away mode is on."""
return self._away_mode
@property
def is_on(self):
"""Return true if the device is on."""
return self._on
@property
def current_hvac(self):
"""Return current operation ie. heat, auto, off."""
return self._current_hvac_mode
def set_temperature(self, **kwargs):
"""Set new target temperatures."""
if kwargs.get(ATTR_TEMPERATURE) is not None:
self._device.set_new_temperature(kwargs.get(ATTR_TEMPERATURE))
def turn_away_mode_on(self):
"""Turn away mode on."""
self._away_mode = True
def turn_away_mode_off(self):
"""Turn away mode off."""
self._away_mode = False
def set_hvac_mode(self, hvac_mode):
"""Set hvac mode."""
if hvac_mode == HVAC_MODE_HEAT:
self._hvac_mode = HVAC_MODE_HEAT
self._device.set_temperature_to_manual()
elif hvac_mode == HVAC_MODE_AUTO:
self._hvac_mode = HVAC_MODE_AUTO
self._device.set_temperature_to_auto()
elif hvac_mode == HVAC_MODE_OFF:
self._hvac_mode = HVAC_MODE_OFF
self._device.set_location_to_off()
else:
_LOGGER.error("Unrecognized hvac mode: %s", hvac_mode)
return
# Ensure we update the current operation after changing the mode
self.schedule_update_ha_state()
def set_preset_mode(self, preset_mode):
if self._on == False:
return
if preset_mode == PRESET_AWAY:
if self._away_mode == False:
self._awaymodeLastState = self._hvac_mode
self._away_mode = True
self.set_hvac_mode(HVAC_MODE_OFF)
elif preset_mode == PRESET_HOME:
if self._away_mode == True:
self._away_mode = False
self.set_hvac_mode(self._awaymodeLastState)
else:
_LOGGER.error("Unknown mode: %s", preset_mode)
self.schedule_update_ha_state()
def turn_on(self):
"""Turn on."""
self._on = True
self._device.set_temperature_to_manual()
def turn_off(self):
"""Turn off."""
self._on = False
self._device.set_location_to_off()
def update(self):
"""Fetch new state data for this device.
This is the only method that should fetch new data for Home Assistant.
"""
if not self._device.update_room():
_LOGGER.error("Updating Warmup component failed")
# set operation mode
self._current_hvac_mode = self.mode_map.get(
self._device.get_run_mode())
# set whether device is in away mode
if self._device.get_run_mode() == 'away':
self._away_mode = True
else:
self._away_mode = False
# set whether device is on/off
if self._device.get_run_mode() == 'off':
self._on = False
else:
self._on = True
`
Also noted on the pypi release Alex left it at version 0.1.5
Hi 8osman - funnily enough I did exactly the same thing to make it work for myself - I have not programmed since my old C++ days so half did this for learning python etc too.
My attempt can be found at: https://github.com/PtolemyIV/warmup4ie/blob/master/climate.py
If anyone tests it more extensively and finds obvious issues etc, please let me know since this was hacked together in a few hours . Alex - I am obviously not a contributor for your repository so please feel free to take this and incorporate as you see fit and I will delete from my account to avoid risk of confusion.
The one issue that I found is that, at least on the official WarmUp app, the location modes apply across all rooms - I have 3 different warmup rooms at home and obviously each climate lovelace card (I am using simple-thermostat) has its own "Heat, Auto, Off" buttons - if you click Off on one room, then all the rooms get turned off. However, if you then click Auto, only that individual room gets turned on again. So its a little odd/inconsistent.
haha, well done, better job than me! 👍
Please test it first..! Seems to work okay for me aside from location vs room issue I mention above... I'd also more generally like to have the single component call set up climate devices for all the rooms rather than needing to set up each individually (and could more readily get any device being switched back on, switch back on all the other devices)
The feature I really want on all my climate devices is a "temporary boost" button - i.e. turn on the heating for an hour in a specific room - i know you can do with scripts but both warmup and tado support these timed overrides.
I'm testing this now. First problem is that if the mode is override you get a key error but I think that is related to the warmup api - another PR i've done to expose more data should fix that.
https://github.com/alex-0103/warmup4IE/pull/6
I do feel the fact that if you have more than one device this is horribly inefficient as it polls the API and downloads every devices data each time you call update_room. So I have 5 devices so I make 5 api calls but on each one I get all the data so I could just make one. I'm going to see if I can fix that.
@foxy82 - Thank you for your work on this. I've got 4 warmup4ie's installed, so I too would be very interested in some restructuring that would make things a bit more efficient.
This might belong in a separate issue.
The current API uses one object to represent the connection and the current device. (The current device appears to be a room in warmup's terms, ) The queries used currently operate on all of the devices (rooms) and the data for the room other than the selected one is thrown away. (I don't know if multiple locations existed under one account if the API calls to warmup would return all locations and all devices at once.)
I think it might make sense to have an object that represents the connection to warmup and then a device object for each room would make more sense.
The connection object should probably keep track of when the data was last updated.
For use outside of home assistant, I'd prefer a model where the connection would return a list of locations/devices, or list of objects for each device, so no hard coded configuration for location names and room names would be needed. It's possible this model would also work better with home assistant auto discovery, but I don't know much about that yet. Currently __init__
calls self.get_all_devices
which essentially does this.
Also, currently __init__
doesn't require a location or room name. When an object is instantiated without that, it seems to default to the first device. I don't know if that is supposed to work that way or not. If called without location/room names it could return a list of devices or objects.
The question is whether the break the currently exposed API at this point or not.
Thoughts?
@PtolemyIV I've taken your work and exteded to reduce the number of API calls as well as some other good things. All in this PR: https://github.com/alex-0103/warmup4IE/pull/8
If you can try it out and let me know how you get on that would be great. @rct also any feedback would be appreciated.
Excellent will try it when back (in 10 days only tho)
hi folks, just wanted to give a livesign. Indeed i was very busy the last months and was even unable to check the issues that have been raised in the last months. After having upgraded my own HA installation to the latest version I can confirm that my original code was broken due to changes in HA that were introduced in Versions 0.9x+. I have checked the updated climate.py that has been submitted by @PtolemyIV at https://github.com/PtolemyIV/warmup4ie and confirm that this works for me. Very good work! Thanks! Since i only work occasionally on this project, maybe someone is interested to take over this component and make it an official part HA? I attempted this in summer 2019 but then HA introduced breaking changes and I had no time to rewrite the code. regards Alex
Thanks for all your work so far. PR #8 goes a little further and I've made it so that if you have multiple thermostats it updates them in a single call to My Warmup. Also it will auto detect and add all thermostats to HA that are in a warm-up account. However all of that will require a new version of the API being pushed to pypi. How do you feel about that? If you are happy I will try to get it integrated into HA.
Thanks for all your work so far. PR #8 goes a little further and I've made it so that if you have multiple thermostats it updates them in a single call to My Warmup. Also it will auto detect and add all thermostats to HA that are in a warm-up account. However all of that will require a new version of the API being pushed to pypi. How do you feel about that? If you are happy I will try to get it integrated into HA.
I agree this makes sense and thanks both
Thanks for all your work so far. PR #8 goes a little further and I've made it so that if you have multiple thermostats it updates them in a single call to My Warmup. Also it will auto detect and add all thermostats to HA that are in a warm-up account. However all of that will require a new version of the API being pushed to pypi. How do you feel about that? If you are happy I will try to get it integrated into HA. What changes would be necessary? Please feel free to enhance the code as you see fit. regards Alex
They are all in PR #8 I made the API so you have a class representing the connection and another one for the devices. The connection then only requires a username/password and will return a device for everything it finds. Calling update will then update will devices. I've also fixed up warmup_cc to work with this.
@foxy82
@PtolemyIV I've taken your work and exteded to reduce the number of API calls as well as some other good things. All in this PR:
8
If you can try it out and let me know how you get on that would be great. @rct also any feedback would be appreciated.
I've given this a try, it looks like it doesn't need as much setup in configuration.yaml as previous no name no location no room
I had to change the domain in climate.py to warmup_cc from warmup otherwise it was getting lost...
Also in the warmup4ie folder under main.py are maybe a couple of details that need addressing?
You've put a load of good work into this, which is awesome. Some things are working better, some maybe need a bit more tweaking.
Boost is showing as an option within climate display, but fails to make call..... I would guess these parameters need to be set?
Looks like great progress 👍
I've given this a try, it looks like it doesn't need as much setup in configuration.yaml as previous no name no location no room
Correct it will load all thermostats it finds under the warmup account and will use the name they have on the account. I only have one location on my account so haven't tested multiple locations but it should work.
I had to change the domain in climate.py to warmup_cc from warmup otherwise it was getting lost...
Yeah I've made this as if it will be a full component rather than a custom component (which.is what I assume the cc stands for). If you change configuration.yaml to be warmup instead of warmup_cc it should work without modifying the domain.
Also in the warmup4ie folder under main.py are maybe a couple of details that need addressing?
You've put a load of good work into this, which is awesome. Some things are working better, some maybe need a bit more tweaking.
Sure what do you think needs changing?
Boost is showing as an option within climate display, but fails to make call..... I would guess these parameters need to be set?
Interesting I added boost but then thought I removed it for that reason. To confirm how are you "boosting" in the UI? Boosting is interesting for the warmup I'd imagine that is an override for an amount of time? If so what would we suggest? 1 hour of additional heat? Would we need a boost temp or just X degrees above the current setting? I have created a service that allows you to do an override specifying the temperature and length of the boost perhaps with that we can disable a direct boost from the UI?
Looks like great progress
Thanks and thanks for testing/feeding back. Happy new year.
Hi @foxy82 @8osman @PtolemyIV - it's great to see others all keen on moving this work on in alex's absence. When I checked before xmas foxy's fork had the most recent work so I worked on a PR https://github.com/foxy82/warmup4IE/pull/1 for that. However I now wonder if Ptolemy's is not the most recent?
What I have done is created a new owner https://github.com/ha-warmup and as soon as we choose between our forks whichever is the most up to date I will fork that in and make you contributors so that we can work together.
If you want to compare my fork please see https://github.com/artmg/warmup4IE/tree/ft_init_loader
Looking forward to driving this integration forward together. Cheers, Art
Thanks - foxy82's is the latest. I'll remove my github shortly to avoid confusion. And will also get around to testing his as well.
On Sat, 4 Jan 2020, 15:22 Art M. Gallagher, notifications@github.com wrote:
Hi @foxy82 https://github.com/foxy82 @8osman https://github.com/8osman @PtolemyIV https://github.com/PtolemyIV - it's great to see others all keen on moving this work on in alex's absence. When I checked before xmas foxy's fork had the most recent work so I worked on a PR foxy82#1 https://github.com/foxy82/warmup4IE/pull/1 for that. However I now wonder if Ptolemy's is not the most recent?
What I have done is created a new owner https://github.com/ha-warmup https://github.com/ha-warmup and as soon as we choose between our forks whichever is the most up to date I will fork that in and make you contributors so that we can work together.
- Please vote whichever of your forks you think is the furthest ahead so I can fork it and we can start
- Please also mention if you want to start a channel for dev discussions like reddit or discus.
If you want to compare my fork please see https://github.com/artmg/warmup4IE/tree/ft_init_loader
Looking forward to driving this integration forward together. Cheers, Art
— You are receiving this because you were mentioned. Reply to this email directly, view it on GitHub https://github.com/alex-0103/warmup4IE/issues/4?email_source=notifications&email_token=AAEEYZ7I5NFJGCGGMGJRHZDQ4CSRNA5CNFSM4I4V6CMKYY3PNVWWK3TUL52HS4DFVREXG43VMVBW63LNMVXHJKTDN5WW2ZLOORPWSZGOEICZ6GA#issuecomment-570793752, or unsubscribe https://github.com/notifications/unsubscribe-auth/AAEEYZ6N4XYZSXOWAQWKFILQ4CSRNANCNFSM4I4V6CMA .
so we now have https://github.com/ha-warmup/warmup4IE and I have made us all contributors. Let's use the Issues for managing important things that need resolving with the codebase. Hopefully putting our heads together will make it easier for us all.
@alex-0103
hi folks, just wanted to give a livesign. Indeed i was very busy the last months and was even unable to check the issues that have been raised in the last months. ... Since i only work occasionally on this project, maybe someone is interested to take over this component and make it an official part HA?
I just raised you PR #9 so visitors can see what doesn't work and where to go to get a newer version of this component. Many thanks for giving us such a great base to work from!
Hi, just want to know if you are still working with this?
It was a great little tool when it was working and it's a shame it's not anymore. completely understand that this is something that only gets done in spare time for free.