-
-
Notifications
You must be signed in to change notification settings - Fork 32.1k
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
Eq3btsmart more reliable #11555
Eq3btsmart more reliable #11555
Conversation
@@ -175,5 +179,11 @@ def update(self): | |||
from bluepy.btle import BTLEException | |||
try: | |||
self._thermostat.update() | |||
if self._target_temperature and self._thermostat.target_temperature != self._target_temperature: | |||
self.set_temperature(temperature=self._target_temperature) | |||
if self._target_mode and self.modes[self._thermostat.mode] != self._target_mode: |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
line too long (92 > 79 characters)
@@ -175,5 +179,11 @@ def update(self): | |||
from bluepy.btle import BTLEException | |||
try: | |||
self._thermostat.update() | |||
if self._target_temperature and self._thermostat.target_temperature != self._target_temperature: |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
line too long (108 > 79 characters)
!= self._target_temperature): | ||
self.set_temperature(temperature=self._target_temperature) | ||
if (self._target_mode and | ||
self.modes[self._thermostat.mode] != self._target_mode): |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
visually indented line with same indent as next logical line
self._thermostat.target_temperature | ||
!= self._target_temperature): | ||
self.set_temperature(temperature=self._target_temperature) | ||
if (self._target_mode and |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
trailing whitespace
@@ -175,5 +179,14 @@ def update(self): | |||
from bluepy.btle import BTLEException | |||
try: | |||
self._thermostat.update() | |||
if (self._target_temperature and | |||
self._thermostat.target_temperature | |||
!= self._target_temperature): |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
continuation line over-indented for visual indent
@@ -175,5 +179,14 @@ def update(self): | |||
from bluepy.btle import BTLEException | |||
try: | |||
self._thermostat.update() | |||
if (self._target_temperature and | |||
self._thermostat.target_temperature |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
trailing whitespace
@@ -175,5 +179,14 @@ def update(self): | |||
from bluepy.btle import BTLEException | |||
try: | |||
self._thermostat.update() | |||
if (self._target_temperature and |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
trailing whitespace
@@ -175,5 +179,14 @@ def update(self): | |||
from bluepy.btle import BTLEException | |||
try: | |||
self._thermostat.update() | |||
if (self._target_temperature and | |||
self._thermostat.target_temperature | |||
!= self._target_temperature): |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
visually indented line with same indent as next logical line
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is not a good change. If the target temperature is changing outside of Home Assistant control, it's not up to Home Assistant to enforce it's target temperature. Instead, Home Assistant should just adopt the target temperature. It's up to the user to write automation if they want to enforce a specific target temperature.
@balloob In case of operation mode this was not the issue, as my changes were assuming turning on "Boost" mode which turns back to "Manual"/"Auto" automatically after few minutes. HA with my changes was allowing it to change back from "Boost" and it was working fine. |
While I have the same objection as @balloob , I was actually thinking about implementing something like this myself. That bluetooth connection is really unreliable. And there's only like two meters between my raspberry pi and the thermostat. I think "retry until the requested value was reported back once, then behave as before" might be a good compromise. Also, one should probably make this configurable, and set the default to |
So, I have discussed about this topic now multiple times on different topics (wrt eq3bt, ble tracker, mi flora), and instead of simply stating that it's a problem that has to be fixed on a higher level, e.g. by doing bluetooth access sequentially I decided that it's time to do some non-scientific measurements on it. For that I created a small script which connects to the device, fetches its state and disconnects, and does this first sequentially for a hundred time per device. Then the same test is repeated with multiple thread setups to verify if the hypothesis about thread usage / concurrent access could indeed the problem. The script can be seen in https://gist.github.com/anonymous/8e303b8a01e9fc9c44cbc08e3a96cfdc . To try this you need to modify I run this script on a raspberry pi 3 against two thermostats with no other bluetooth-accessing programs active (besides bluetoothd). Results:
Some remarks:
So based on this, my suggestion remains the same as before. Assuming this is really a limitation on the hardware / bluetooth stack of the Pi, the bluetooth accesses done by homeassistant should be done sequentially (no matter what backend lib they are using, if this is not a bluepy limitation, which I doubt). Looking at results with 2 threads this would indicate that if 15% failure rate is accepted, up to 2 btle connections can be made on pi3 concurrently. It has to be noted though, that the execution ordering in threaded use was not enforced (if it's not done by the threadpoolexecutor), which may skew the results. What could be interesting however would be the following:
Please feel to experiment and report back on your findings & ideas :-) edit: to the original proposal, it may very well make sense to batch the change to happen during the upcoming update instead of trying to do it like it is currently done. edit2: on related note to miflora, I think I have seen recommendations to use a miflora-mqtt gateway and let homeassistant fetch from it. That would corroborate that the issue is indeed with concurrent accessing. |
python-eq3bt 0.1.8 raises the exceptions like it should, so no need to modify the connection.py for testing this. |
@balloob |
In case someone finds it useful, I've wrote simple eq3 <-> mqtt gateway that works stable for me. Its doing sequential updates over defined thermostats ( and possible other bt devices like xiaomi scale ). I hope you don't mind hijacking thread. https://github.com/zewelor/bt-mqtt-gateway |
Current implementation is ok as it is only temporarily enforced. |
@rytilahti I would be 👍 if we come up with our own bluetooth controller that enforces sequential access. Would just be a pain to make sure that all integrations use it 😞 makes integrations no longer generic. |
Thanks @karlkar and @rytilahti for the work done on eq3bt in 0.64.0, the valves management is indeed much more reliable now! |
It is all thanks to @karlkar, I was merely an observer here :-) |
Description:
Applying these changes makes eq3btsmart thermostat remember the temperature/operation mode set by the user.
During update (performed every minute) it performs a check if the current thermostat settings are the same as user wants them to. If not, temperature/operation mode are changed.
After applying the changes temperature/operation mode are set almost immediately in most cases, as update is performed after every set_temperature/set_operation_mode and repeated in case of failure 2 times.
Code was running on my local HA instance for about 1 week and everything was working much better than before.
Related issue (if applicable): fixes #11554
Pull request in home-assistant.github.io with documentation (if applicable): home-assistant/home-assistant.github.io#<home-assistant.github.io PR number goes here>
Example entry for
configuration.yaml
(if applicable):Checklist:
If user exposed functionality or configuration variables are added/changed:
If the code communicates with devices, web services, or third-party tools:
tox
run successfully. Your PR cannot be merged unless tests passREQUIREMENTS
variable (example).requirements_all.txt
by runningscript/gen_requirements_all.py
..coveragerc
.If the code does not interact with devices:
tox
run successfully. Your PR cannot be merged unless tests pass