steamloop 1.2.2__tar.gz → 1.2.3__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (29) hide show
  1. {steamloop-1.2.2 → steamloop-1.2.3}/PKG-INFO +1 -1
  2. {steamloop-1.2.2 → steamloop-1.2.3}/pyproject.toml +1 -1
  3. {steamloop-1.2.2 → steamloop-1.2.3}/src/steamloop/__init__.py +1 -1
  4. {steamloop-1.2.2 → steamloop-1.2.3}/src/steamloop/connection.py +17 -4
  5. {steamloop-1.2.2 → steamloop-1.2.3}/src/steamloop/const.py +2 -0
  6. {steamloop-1.2.2 → steamloop-1.2.3}/src/steamloop.egg-info/PKG-INFO +1 -1
  7. {steamloop-1.2.2 → steamloop-1.2.3}/tests/test_connection.py +16 -0
  8. {steamloop-1.2.2 → steamloop-1.2.3}/LICENSE +0 -0
  9. {steamloop-1.2.2 → steamloop-1.2.3}/README.md +0 -0
  10. {steamloop-1.2.2 → steamloop-1.2.3}/setup.cfg +0 -0
  11. {steamloop-1.2.2 → steamloop-1.2.3}/src/steamloop/__main__.py +0 -0
  12. {steamloop-1.2.2 → steamloop-1.2.3}/src/steamloop/certs.py +0 -0
  13. {steamloop-1.2.2 → steamloop-1.2.3}/src/steamloop/cli.py +0 -0
  14. {steamloop-1.2.2 → steamloop-1.2.3}/src/steamloop/exceptions.py +0 -0
  15. {steamloop-1.2.2 → steamloop-1.2.3}/src/steamloop/models.py +0 -0
  16. {steamloop-1.2.2 → steamloop-1.2.3}/src/steamloop/py.typed +0 -0
  17. {steamloop-1.2.2 → steamloop-1.2.3}/src/steamloop.egg-info/SOURCES.txt +0 -0
  18. {steamloop-1.2.2 → steamloop-1.2.3}/src/steamloop.egg-info/dependency_links.txt +0 -0
  19. {steamloop-1.2.2 → steamloop-1.2.3}/src/steamloop.egg-info/entry_points.txt +0 -0
  20. {steamloop-1.2.2 → steamloop-1.2.3}/src/steamloop.egg-info/requires.txt +0 -0
  21. {steamloop-1.2.2 → steamloop-1.2.3}/src/steamloop.egg-info/top_level.txt +0 -0
  22. {steamloop-1.2.2 → steamloop-1.2.3}/tests/test_certs.py +0 -0
  23. {steamloop-1.2.2 → steamloop-1.2.3}/tests/test_cli.py +0 -0
  24. {steamloop-1.2.2 → steamloop-1.2.3}/tests/test_const.py +0 -0
  25. {steamloop-1.2.2 → steamloop-1.2.3}/tests/test_dunder_main.py +0 -0
  26. {steamloop-1.2.2 → steamloop-1.2.3}/tests/test_exceptions.py +0 -0
  27. {steamloop-1.2.2 → steamloop-1.2.3}/tests/test_models.py +0 -0
  28. {steamloop-1.2.2 → steamloop-1.2.3}/tests/test_pairing.py +0 -0
  29. {steamloop-1.2.2 → steamloop-1.2.3}/tests/test_protocol.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: steamloop
3
- Version: 1.2.2
3
+ Version: 1.2.3
4
4
  Summary: Local control for choochoo based thermostats
5
5
  Author-email: "J. Nick Koston" <nick@koston.org>
6
6
  License-Expression: Apache-2.0
@@ -4,7 +4,7 @@ requires = [ "setuptools>=77.0.3" ]
4
4
 
5
5
  [project]
6
6
  name = "steamloop"
7
- version = "1.2.2"
7
+ version = "1.2.3"
8
8
  description = "Local control for choochoo based thermostats"
9
9
  readme = "README.md"
10
10
  license = "Apache-2.0"
@@ -1,6 +1,6 @@
1
1
  """Local control for thermostat devices over mTLS."""
2
2
 
3
- __version__ = "1.2.2"
3
+ __version__ = "1.2.3"
4
4
 
5
5
  from .connection import ThermostatConnection, load_pairing, save_pairing
6
6
  from .const import DEFAULT_PORT, FanMode, HoldType, ZoneMode
@@ -21,6 +21,8 @@ from .certs import CERT_SETS, CertSet, create_ssl_context
21
21
  from .const import (
22
22
  BACKOFF_FACTOR,
23
23
  CONNECT_TIMEOUT,
24
+ DEFAULT_COOL_SETPOINT,
25
+ DEFAULT_HEAT_SETPOINT,
24
26
  DEFAULT_PORT,
25
27
  HEARTBEAT_INTERVAL,
26
28
  INITIAL_STATE_TIMEOUT,
@@ -725,10 +727,21 @@ class ThermostatConnection:
725
727
  db = float(zone.deadband) if zone and zone.deadband else 3.0
726
728
  heat_requested = heat_setpoint is not None
727
729
  cool_requested = cool_setpoint is not None
728
- if heat_setpoint is None:
729
- heat_setpoint = zone.heat_setpoint if zone else "55"
730
- if cool_setpoint is None:
731
- cool_setpoint = zone.cool_setpoint if zone else "75"
730
+ # Fall back to defaults when the value is missing OR empty — a zone
731
+ # can exist before its initial setpoint burst arrives, leaving the
732
+ # stored setpoints as "" which float() cannot parse.
733
+ if not heat_setpoint:
734
+ heat_setpoint = (
735
+ zone.heat_setpoint
736
+ if zone and zone.heat_setpoint
737
+ else DEFAULT_HEAT_SETPOINT
738
+ )
739
+ if not cool_setpoint:
740
+ cool_setpoint = (
741
+ zone.cool_setpoint
742
+ if zone and zone.cool_setpoint
743
+ else DEFAULT_COOL_SETPOINT
744
+ )
732
745
  heat_f = float(heat_setpoint)
733
746
  cool_f = float(cool_setpoint)
734
747
  if cool_f - heat_f < db:
@@ -47,3 +47,5 @@ INITIAL_STATE_TIMEOUT = 1 # seconds to wait for initial state after login
47
47
  RECONNECT_DELAY = 5 # initial delay before first reconnect attempt
48
48
  RECONNECT_MAX = 300 # max delay between reconnect attempts (5 minutes)
49
49
  BACKOFF_FACTOR = 2 # multiply delay by this on each failure
50
+ DEFAULT_HEAT_SETPOINT = "55" # str for wire format
51
+ DEFAULT_COOL_SETPOINT = "75" # str for wire format
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: steamloop
3
- Version: 1.2.2
3
+ Version: 1.2.3
4
4
  Summary: Local control for choochoo based thermostats
5
5
  Author-email: "J. Nick Koston" <nick@koston.org>
6
6
  License-Expression: Apache-2.0
@@ -297,6 +297,22 @@ def test_set_temperature_setpoint_defaults(
297
297
  assert req["deadband"] == "3"
298
298
 
299
299
 
300
+ def test_set_temperature_setpoint_known_zone_empty_setpoints(
301
+ connection: ThermostatConnection,
302
+ ) -> None:
303
+ """A zone discovered before its setpoint burst has empty setpoints.
304
+
305
+ Setting a setpoint then must not crash on float("") — the missing
306
+ opposite setpoint should fall back to the default.
307
+ """
308
+ connection.state.zones["1"] = Zone(zone_id="1") # no setpoints yet
309
+ connection.set_temperature_setpoint("1", heat_setpoint="72")
310
+ msg = _get_sent_message(connection)
311
+ req = msg["Request"]["UpdateTemperatureSetpoint"]
312
+ assert req["heat_setpoint"] == "72"
313
+ assert req["cool_setpoint"] == "75" # default, deadband already satisfied
314
+
315
+
300
316
  def test_set_fan_mode(connection: ThermostatConnection) -> None:
301
317
  connection.set_fan_mode(FanMode.CIRCULATE)
302
318
  msg = _get_sent_message(connection)
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes