python-selve-new 2.5.2__tar.gz → 2.5.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 (109) hide show
  1. {python_selve_new-2.5.2 → python_selve_new-2.5.3}/PKG-INFO +1 -1
  2. {python_selve_new-2.5.2 → python_selve_new-2.5.3}/python_selve_new.egg-info/PKG-INFO +1 -1
  3. {python_selve_new-2.5.2 → python_selve_new-2.5.3}/selve/__init__.py +50 -25
  4. {python_selve_new-2.5.2 → python_selve_new-2.5.3}/selve/_version.py +3 -3
  5. {python_selve_new-2.5.2 → python_selve_new-2.5.3}/tests/integration/test_selve_gateway_integration.py +1 -1
  6. {python_selve_new-2.5.2 → python_selve_new-2.5.3}/tests/unit/test_selve_edge_cases.py +3 -2
  7. {python_selve_new-2.5.2 → python_selve_new-2.5.3}/tests/unit/test_selve_init_comprehensive.py +2 -1
  8. {python_selve_new-2.5.2 → python_selve_new-2.5.3}/.github/FUNDING.yml +0 -0
  9. {python_selve_new-2.5.2 → python_selve_new-2.5.3}/.github/architect.chatmode.md +0 -0
  10. {python_selve_new-2.5.2 → python_selve_new-2.5.3}/.github/ask.chatmode.md +0 -0
  11. {python_selve_new-2.5.2 → python_selve_new-2.5.3}/.github/code.chatmode.md +0 -0
  12. {python_selve_new-2.5.2 → python_selve_new-2.5.3}/.github/debug.chatmode.md +0 -0
  13. {python_selve_new-2.5.2 → python_selve_new-2.5.3}/.github/workflows/python-publish.yml +0 -0
  14. {python_selve_new-2.5.2 → python_selve_new-2.5.3}/.github/workflows/tests.yml +0 -0
  15. {python_selve_new-2.5.2 → python_selve_new-2.5.3}/.gitignore +0 -0
  16. {python_selve_new-2.5.2 → python_selve_new-2.5.3}/.idea/.gitignore +0 -0
  17. {python_selve_new-2.5.2 → python_selve_new-2.5.3}/.idea/inspectionProfiles/profiles_settings.xml +0 -0
  18. {python_selve_new-2.5.2 → python_selve_new-2.5.3}/.idea/misc.xml +0 -0
  19. {python_selve_new-2.5.2 → python_selve_new-2.5.3}/.idea/modules.xml +0 -0
  20. {python_selve_new-2.5.2 → python_selve_new-2.5.3}/.idea/python-selve-new.iml +0 -0
  21. {python_selve_new-2.5.2 → python_selve_new-2.5.3}/.idea/vcs.xml +0 -0
  22. {python_selve_new-2.5.2 → python_selve_new-2.5.3}/CHANGELOG.md +0 -0
  23. {python_selve_new-2.5.2 → python_selve_new-2.5.3}/LICENSE +0 -0
  24. {python_selve_new-2.5.2 → python_selve_new-2.5.3}/README.md +0 -0
  25. {python_selve_new-2.5.2 → python_selve_new-2.5.3}/coverage_xdist_example.txt +0 -0
  26. {python_selve_new-2.5.2 → python_selve_new-2.5.3}/debug_response.py +0 -0
  27. {python_selve_new-2.5.2 → python_selve_new-2.5.3}/debug_test.bat +0 -0
  28. {python_selve_new-2.5.2 → python_selve_new-2.5.3}/direct_hardware_test.bat +0 -0
  29. {python_selve_new-2.5.2 → python_selve_new-2.5.3}/direct_hardware_test.py +0 -0
  30. {python_selve_new-2.5.2 → python_selve_new-2.5.3}/generate_coverage.bat +0 -0
  31. {python_selve_new-2.5.2 → python_selve_new-2.5.3}/package.sh +0 -0
  32. {python_selve_new-2.5.2 → python_selve_new-2.5.3}/pyproject.toml +0 -0
  33. {python_selve_new-2.5.2 → python_selve_new-2.5.3}/python_selve_new.egg-info/SOURCES.txt +0 -0
  34. {python_selve_new-2.5.2 → python_selve_new-2.5.3}/python_selve_new.egg-info/dependency_links.txt +0 -0
  35. {python_selve_new-2.5.2 → python_selve_new-2.5.3}/python_selve_new.egg-info/requires.txt +0 -0
  36. {python_selve_new-2.5.2 → python_selve_new-2.5.3}/python_selve_new.egg-info/top_level.txt +0 -0
  37. {python_selve_new-2.5.2 → python_selve_new-2.5.3}/release.py +0 -0
  38. {python_selve_new-2.5.2 → python_selve_new-2.5.3}/run_all_tests.bat +0 -0
  39. {python_selve_new-2.5.2 → python_selve_new-2.5.3}/run_hardware_tests.bat +0 -0
  40. {python_selve_new-2.5.2 → python_selve_new-2.5.3}/run_integration_tests.bat +0 -0
  41. {python_selve_new-2.5.2 → python_selve_new-2.5.3}/run_mock_tests.bat +0 -0
  42. {python_selve_new-2.5.2 → python_selve_new-2.5.3}/run_single_test.bat +0 -0
  43. {python_selve_new-2.5.2 → python_selve_new-2.5.3}/run_tests.bat +0 -0
  44. {python_selve_new-2.5.2 → python_selve_new-2.5.3}/selve/commands/__init__.py +0 -0
  45. {python_selve_new-2.5.2 → python_selve_new-2.5.3}/selve/commands/command.py +0 -0
  46. {python_selve_new-2.5.2 → python_selve_new-2.5.3}/selve/commands/device.py +0 -0
  47. {python_selve_new-2.5.2 → python_selve_new-2.5.3}/selve/commands/event.py +0 -0
  48. {python_selve_new-2.5.2 → python_selve_new-2.5.3}/selve/commands/firmware.py +0 -0
  49. {python_selve_new-2.5.2 → python_selve_new-2.5.3}/selve/commands/group.py +0 -0
  50. {python_selve_new-2.5.2 → python_selve_new-2.5.3}/selve/commands/iveo.py +0 -0
  51. {python_selve_new-2.5.2 → python_selve_new-2.5.3}/selve/commands/param.py +0 -0
  52. {python_selve_new-2.5.2 → python_selve_new-2.5.3}/selve/commands/senSim.py +0 -0
  53. {python_selve_new-2.5.2 → python_selve_new-2.5.3}/selve/commands/sender.py +0 -0
  54. {python_selve_new-2.5.2 → python_selve_new-2.5.3}/selve/commands/sensor.py +0 -0
  55. {python_selve_new-2.5.2 → python_selve_new-2.5.3}/selve/commands/service.py +0 -0
  56. {python_selve_new-2.5.2 → python_selve_new-2.5.3}/selve/device.py +0 -0
  57. {python_selve_new-2.5.2 → python_selve_new-2.5.3}/selve/gateway.py +0 -0
  58. {python_selve_new-2.5.2 → python_selve_new-2.5.3}/selve/group.py +0 -0
  59. {python_selve_new-2.5.2 → python_selve_new-2.5.3}/selve/iveo.py +0 -0
  60. {python_selve_new-2.5.2 → python_selve_new-2.5.3}/selve/senSim.py +0 -0
  61. {python_selve_new-2.5.2 → python_selve_new-2.5.3}/selve/sender.py +0 -0
  62. {python_selve_new-2.5.2 → python_selve_new-2.5.3}/selve/sensor.py +0 -0
  63. {python_selve_new-2.5.2 → python_selve_new-2.5.3}/selve/util/__init__.py +0 -0
  64. {python_selve_new-2.5.2 → python_selve_new-2.5.3}/selve/util/errors.py +0 -0
  65. {python_selve_new-2.5.2 → python_selve_new-2.5.3}/selve/util/protocol.py +0 -0
  66. {python_selve_new-2.5.2 → python_selve_new-2.5.3}/selve/util/serial_transport.py +0 -0
  67. {python_selve_new-2.5.2 → python_selve_new-2.5.3}/setup.cfg +0 -0
  68. {python_selve_new-2.5.2 → python_selve_new-2.5.3}/setup.py +0 -0
  69. {python_selve_new-2.5.2 → python_selve_new-2.5.3}/setup_and_test.bat +0 -0
  70. {python_selve_new-2.5.2 → python_selve_new-2.5.3}/tests/__init__.py +0 -0
  71. {python_selve_new-2.5.2 → python_selve_new-2.5.3}/tests/conftest.py +0 -0
  72. {python_selve_new-2.5.2 → python_selve_new-2.5.3}/tests/integration/README.md +0 -0
  73. {python_selve_new-2.5.2 → python_selve_new-2.5.3}/tests/integration/__init__.py +0 -0
  74. {python_selve_new-2.5.2 → python_selve_new-2.5.3}/tests/integration/conftest.py +0 -0
  75. {python_selve_new-2.5.2 → python_selve_new-2.5.3}/tests/integration/test_device_integration.py +0 -0
  76. {python_selve_new-2.5.2 → python_selve_new-2.5.3}/tests/integration/test_selve_hardware.py +0 -0
  77. {python_selve_new-2.5.2 → python_selve_new-2.5.3}/tests/integration/test_selve_integration.py +0 -0
  78. {python_selve_new-2.5.2 → python_selve_new-2.5.3}/tests/test_import.py +0 -0
  79. {python_selve_new-2.5.2 → python_selve_new-2.5.3}/tests/test_replacement.py +0 -0
  80. {python_selve_new-2.5.2 → python_selve_new-2.5.3}/tests/unit/__init__.py +0 -0
  81. {python_selve_new-2.5.2 → python_selve_new-2.5.3}/tests/unit/mock_utils.py +0 -0
  82. {python_selve_new-2.5.2 → python_selve_new-2.5.3}/tests/unit/test_command_coverage.py +0 -0
  83. {python_selve_new-2.5.2 → python_selve_new-2.5.3}/tests/unit/test_commands.py +0 -0
  84. {python_selve_new-2.5.2 → python_selve_new-2.5.3}/tests/unit/test_device.py +0 -0
  85. {python_selve_new-2.5.2 → python_selve_new-2.5.3}/tests/unit/test_device_classes_coverage.py +0 -0
  86. {python_selve_new-2.5.2 → python_selve_new-2.5.3}/tests/unit/test_device_commands_extended.py +0 -0
  87. {python_selve_new-2.5.2 → python_selve_new-2.5.3}/tests/unit/test_gateway_configuration_issues.py +0 -0
  88. {python_selve_new-2.5.2 → python_selve_new-2.5.3}/tests/unit/test_gateway_error_handling_fixed.py +0 -0
  89. {python_selve_new-2.5.2 → python_selve_new-2.5.3}/tests/unit/test_group.py +0 -0
  90. {python_selve_new-2.5.2 → python_selve_new-2.5.3}/tests/unit/test_group_commands.py +0 -0
  91. {python_selve_new-2.5.2 → python_selve_new-2.5.3}/tests/unit/test_missing_components.py +0 -0
  92. {python_selve_new-2.5.2 → python_selve_new-2.5.3}/tests/unit/test_mock_commands.py +0 -0
  93. {python_selve_new-2.5.2 → python_selve_new-2.5.3}/tests/unit/test_mock_devices_and_groups.py +0 -0
  94. {python_selve_new-2.5.2 → python_selve_new-2.5.3}/tests/unit/test_mock_sensors_and_senders.py +0 -0
  95. {python_selve_new-2.5.2 → python_selve_new-2.5.3}/tests/unit/test_param_commands_extended.py +0 -0
  96. {python_selve_new-2.5.2 → python_selve_new-2.5.3}/tests/unit/test_port_discovery.py +0 -0
  97. {python_selve_new-2.5.2 → python_selve_new-2.5.3}/tests/unit/test_selve_advanced_coverage.py +0 -0
  98. {python_selve_new-2.5.2 → python_selve_new-2.5.3}/tests/unit/test_selve_core_coverage.py +0 -0
  99. {python_selve_new-2.5.2 → python_selve_new-2.5.3}/tests/unit/test_selve_gateway.py +0 -0
  100. {python_selve_new-2.5.2 → python_selve_new-2.5.3}/tests/unit/test_selve_init_response_coverage.py +0 -0
  101. {python_selve_new-2.5.2 → python_selve_new-2.5.3}/tests/unit/test_selve_init_simple.py +0 -0
  102. {python_selve_new-2.5.2 → python_selve_new-2.5.3}/tests/unit/test_selve_main_class_extensive.py +0 -0
  103. {python_selve_new-2.5.2 → python_selve_new-2.5.3}/tests/unit/test_sender_commands_extended.py +0 -0
  104. {python_selve_new-2.5.2 → python_selve_new-2.5.3}/tests/unit/test_sensim_commands_extended.py +0 -0
  105. {python_selve_new-2.5.2 → python_selve_new-2.5.3}/tests/unit/test_sensor_commands_extended.py +0 -0
  106. {python_selve_new-2.5.2 → python_selve_new-2.5.3}/tests/unit/test_service_command_errors.py +0 -0
  107. {python_selve_new-2.5.2 → python_selve_new-2.5.3}/tests/unit/test_service_commands.py +0 -0
  108. {python_selve_new-2.5.2 → python_selve_new-2.5.3}/tests/unit/test_util.py +0 -0
  109. {python_selve_new-2.5.2 → python_selve_new-2.5.3}/tests/unit/test_utility_coverage.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: python-selve-new
3
- Version: 2.5.2
3
+ Version: 2.5.3
4
4
  Summary: Python library for interfacing with selve devices using the USB-RF controller. Written completely new.
5
5
  Home-page: https://github.com/Kannix2005/python-selve-new
6
6
  Author: Stefan Altheimer
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: python-selve-new
3
- Version: 2.5.2
3
+ Version: 2.5.3
4
4
  Summary: Python library for interfacing with selve devices using the USB-RF controller. Written completely new.
5
5
  Home-page: https://github.com/Kannix2005/python-selve-new
6
6
  Author: Stefan Altheimer
@@ -12,6 +12,7 @@ except ImportError:
12
12
  __version__ = "unknown"
13
13
 
14
14
  import asyncio
15
+ import logging
15
16
  import time
16
17
  from collections import deque
17
18
  from itertools import chain
@@ -109,7 +110,7 @@ class Selve:
109
110
  self.reversedStopPosition = 0
110
111
 
111
112
  #Logger
112
- self._LOGGER = logger
113
+ self._LOGGER: logging.Logger = logger or logging.getLogger(__name__)
113
114
 
114
115
 
115
116
  # Legacy worker was removed in favor of dedicated TX/RX tasks.
@@ -211,16 +212,19 @@ class Selve:
211
212
  await asyncio.sleep(5)
212
213
  self._LOGGER.debug("(Selve Worker): " + "Recovering")
213
214
 
215
+ # Tear down the broken transport, then rebuild it directly without calling
216
+ # _probe_port / stopWorker, which would kill the running TX/dispatch tasks.
214
217
  await self._teardown_transport()
215
218
 
216
219
  if self._port is not None:
217
220
  try:
218
- if await self._probe_port(self._port, fromConfigFlow=False):
219
- if self.rxQ is not None and self._transport is not None:
220
- await self._transport.start_reader(self.rxQ)
221
- return
221
+ await self._build_transport(self._port)
222
+ if self.rxQ is not None and self._transport is not None:
223
+ await self._transport.start_reader(self.rxQ)
224
+ self._LOGGER.info("(Selve Worker): Recovery successful on " + str(self._port))
225
+ return
222
226
  except (OSError, IOError) as e:
223
- self._LOGGER.debug("(Selve Worker): " + "Configured port not valid, maybe it has changed, trying other ports...")
227
+ self._LOGGER.debug("(Selve Worker): " + "Configured port not valid, maybe it has changed, trying other ports... " + str(e))
224
228
  except Exception as e:
225
229
  self._LOGGER.error("(Selve Worker): " + "Unknown exception: " + str(e))
226
230
 
@@ -235,10 +239,12 @@ class Selve:
235
239
 
236
240
  for p in available_ports:
237
241
  try:
238
- if await self._probe_port(p.device, fromConfigFlow=False):
239
- if self.rxQ is not None and self._transport is not None:
240
- await self._transport.start_reader(self.rxQ)
241
- return
242
+ await self._build_transport(p.device)
243
+ self._port = p.device
244
+ if self.rxQ is not None and self._transport is not None:
245
+ await self._transport.start_reader(self.rxQ)
246
+ self._LOGGER.info("(Selve Worker): Recovery successful on " + str(p.device))
247
+ return
242
248
  except Exception as e:
243
249
  self._LOGGER.error("(Selve Worker): " + "Error at com port: " + str(e))
244
250
  else:
@@ -1057,20 +1063,39 @@ class Selve:
1057
1063
  callback(response)
1058
1064
 
1059
1065
 
1060
- def _handleCommandResult(self, response: IveoResultResponse | CommandResultResponse):
1061
-
1062
- # if isinstance(response, IveoResultResponse):
1063
- # for id in response.executedIds:
1064
- # dev = self.getDevice(id, SelveTypes.IVEO)
1065
-
1066
- # if response.command is DriveCommandIveo.DOWN:
1067
- # dev.state = MovementState.DOWN_ON
1068
- # if response.command is DriveCommandIveo.UP:
1069
- # dev.state = MovementState.UP_ON
1070
- # if response.command is DriveCommandIveo.STOP:
1071
- # dev.state = MovementState.STOPPED_OFF
1072
-
1073
- # self.addOrUpdateDevice(dev, SelveTypes.IVEO)
1066
+ def _handleCommandResult(self, response):
1067
+ if isinstance(response, IveoResultResponse):
1068
+ for id in response.executedIds:
1069
+ dev = self.getDevice(id, SelveTypes.IVEO)
1070
+ if dev is None:
1071
+ continue
1072
+ if response.command is DriveCommandIveo.DOWN:
1073
+ dev.state = MovementState.DOWN_ON
1074
+ elif response.command is DriveCommandIveo.UP:
1075
+ dev.state = MovementState.UP_ON
1076
+ elif response.command is DriveCommandIveo.STOP:
1077
+ dev.state = MovementState.STOPPED_OFF
1078
+ self.addOrUpdateDevice(dev, SelveTypes.IVEO)
1079
+
1080
+ elif isinstance(response, CommandResultResponse):
1081
+ for id in response.successIds:
1082
+ dev = self.getDevice(id, SelveTypes.DEVICE)
1083
+ if dev is None:
1084
+ continue
1085
+ dev.unreachable = False
1086
+ if response.command is DriveCommandCommeo.DRIVEDOWN:
1087
+ dev.state = MovementState.DOWN_ON
1088
+ elif response.command is DriveCommandCommeo.DRIVEUP:
1089
+ dev.state = MovementState.UP_ON
1090
+ elif response.command is DriveCommandCommeo.STOP:
1091
+ dev.state = MovementState.STOPPED_OFF
1092
+ self.addOrUpdateDevice(dev, SelveTypes.DEVICE)
1093
+ for id in response.failedIds:
1094
+ dev = self.getDevice(id, SelveTypes.DEVICE)
1095
+ if dev is None:
1096
+ continue
1097
+ dev.unreachable = True
1098
+ self.addOrUpdateDevice(dev, SelveTypes.DEVICE)
1074
1099
 
1075
1100
  for callback in self._callbacks:
1076
1101
  callback()
@@ -1350,7 +1375,7 @@ class Selve:
1350
1375
  else:
1351
1376
  dev.targetValue = 100 - response.targetValue if response.targetValue else 0
1352
1377
 
1353
- dev.unreachable = response.unreachable if response.unreachable else True
1378
+ dev.unreachable = response.unreachable
1354
1379
  dev.overload = response.overload if response.overload else False
1355
1380
  dev.obstructed = response.obstructed if response.obstructed else False
1356
1381
  dev.alarm = response.alarm if response.alarm else False
@@ -18,7 +18,7 @@ version_tuple: tuple[int | str, ...]
18
18
  commit_id: str | None
19
19
  __commit_id__: str | None
20
20
 
21
- __version__ = version = '2.5.2'
22
- __version_tuple__ = version_tuple = (2, 5, 2)
21
+ __version__ = version = '2.5.3'
22
+ __version_tuple__ = version_tuple = (2, 5, 3)
23
23
 
24
- __commit_id__ = commit_id = 'g24c865c13'
24
+ __commit_id__ = commit_id = 'ge708968d7'
@@ -90,6 +90,6 @@ class TestSelveGatewayIntegration:
90
90
  await mock_selve_instance.recover()
91
91
 
92
92
  # Verify logger was called (indicating recover ran)
93
- mock_logger.info.assert_called_with("(Selve Worker): Recover serial connection")
93
+ mock_logger.info.assert_any_call("(Selve Worker): Recover serial connection")
94
94
  mock_logger.debug.assert_any_call("(Selve Worker): Waiting 5 seconds before trying...")
95
95
  mock_logger.debug.assert_any_call("(Selve Worker): Recovering")
@@ -18,8 +18,9 @@ class TestSelveEdgeCases:
18
18
  def test_init_with_none_logger(self):
19
19
  """Test initialization with None logger."""
20
20
  selve = Selve(logger=None)
21
- # None logger should result in None _LOGGER (implementation allows this)
22
- assert selve._LOGGER is None
21
+ # None logger falls back to a module-level logger, never stays None
22
+ import logging
23
+ assert isinstance(selve._LOGGER, logging.Logger)
23
24
 
24
25
  def test_init_with_invalid_port(self):
25
26
  """Test initialization with invalid port."""
@@ -60,7 +60,8 @@ class TestSelveInit:
60
60
  selve = Selve()
61
61
 
62
62
  assert selve._port is None
63
- assert selve._LOGGER is None
63
+ import logging
64
+ assert isinstance(selve._LOGGER, logging.Logger)
64
65
  assert selve.loop is None
65
66
  assert isinstance(selve._callbacks, set)
66
67
  assert isinstance(selve._eventCallbacks, set)