ramses-rf 0.53.3__tar.gz → 0.53.5__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 (391) hide show
  1. {ramses_rf-0.53.3 → ramses_rf-0.53.5}/.github/workflows/check-cov.yml +1 -1
  2. {ramses_rf-0.53.3 → ramses_rf-0.53.5}/.pre-commit-config.yaml +5 -1
  3. {ramses_rf-0.53.3 → ramses_rf-0.53.5}/PKG-INFO +1 -1
  4. {ramses_rf-0.53.3 → ramses_rf-0.53.5}/docs/source/ramses_rf.rst +8 -0
  5. {ramses_rf-0.53.3 → ramses_rf-0.53.5}/pyproject.toml +1 -1
  6. {ramses_rf-0.53.3 → ramses_rf-0.53.5}/ramses_cli/client.py +15 -11
  7. {ramses_rf-0.53.3 → ramses_rf-0.53.5}/ramses_rf/database.py +34 -32
  8. {ramses_rf-0.53.3 → ramses_rf-0.53.5}/ramses_rf/entity_base.py +3 -1
  9. {ramses_rf-0.53.3 → ramses_rf-0.53.5}/ramses_rf/gateway.py +30 -11
  10. {ramses_rf-0.53.3 → ramses_rf-0.53.5}/ramses_rf/storage.py +55 -29
  11. {ramses_rf-0.53.3 → ramses_rf-0.53.5}/ramses_rf/system/heat.py +38 -12
  12. {ramses_rf-0.53.3 → ramses_rf-0.53.5}/ramses_rf/version.py +1 -1
  13. {ramses_rf-0.53.3 → ramses_rf-0.53.5}/ramses_tx/__init__.py +8 -5
  14. {ramses_rf-0.53.3 → ramses_rf-0.53.5}/ramses_tx/const.py +4 -2
  15. {ramses_rf-0.53.3 → ramses_rf-0.53.5}/ramses_tx/gateway.py +28 -16
  16. {ramses_rf-0.53.3 → ramses_rf-0.53.5}/ramses_tx/logger.py +27 -8
  17. {ramses_rf-0.53.3 → ramses_rf-0.53.5}/ramses_tx/parsers.py +1 -0
  18. {ramses_rf-0.53.3 → ramses_rf-0.53.5}/ramses_tx/protocol.py +37 -29
  19. {ramses_rf-0.53.3 → ramses_rf-0.53.5}/ramses_tx/ramses.py +10 -1
  20. {ramses_rf-0.53.3 → ramses_rf-0.53.5}/ramses_tx/transport.py +29 -15
  21. {ramses_rf-0.53.3 → ramses_rf-0.53.5}/ramses_tx/version.py +1 -1
  22. {ramses_rf-0.53.3 → ramses_rf-0.53.5}/requirements/requirements_dev.txt +4 -2
  23. {ramses_rf-0.53.3 → ramses_rf-0.53.5}/tests/deprecated/common.py +1 -1
  24. {ramses_rf-0.53.3 → ramses_rf-0.53.5}/tests/tests/helpers.py +9 -2
  25. {ramses_rf-0.53.3 → ramses_rf-0.53.5}/tests/tests/parsers/code_2210.log +1 -0
  26. {ramses_rf-0.53.3 → ramses_rf-0.53.5}/tests/tests/test_eavesdrop_schema.py +1 -1
  27. ramses_rf-0.53.5/tests/tests/test_hgi_id.py +92 -0
  28. {ramses_rf-0.53.3 → ramses_rf-0.53.5}/tests/tests/test_schemas.py +7 -13
  29. ramses_rf-0.53.5/tests/tests/test_systems.py +203 -0
  30. {ramses_rf-0.53.3 → ramses_rf-0.53.5}/tests/tests_cli/test_client.py +5 -4
  31. {ramses_rf-0.53.3 → ramses_rf-0.53.5}/tests/tests_rf/test_entity_base.py +58 -1
  32. {ramses_rf-0.53.3 → ramses_rf-0.53.5}/tests/tests_rf/test_protocol_fsm.py +3 -2
  33. ramses_rf-0.53.5/tests/tests_rf/test_system_heat.py +140 -0
  34. ramses_rf-0.53.5/tests/tests_tx/test_logger.py +78 -0
  35. ramses_rf-0.53.3/tests/tests/test_systems.py +0 -264
  36. {ramses_rf-0.53.3 → ramses_rf-0.53.5}/.github/ISSUE_TEMPLATE/bug_report.md +0 -0
  37. {ramses_rf-0.53.3 → ramses_rf-0.53.5}/.github/dependabot.yml +0 -0
  38. {ramses_rf-0.53.3 → ramses_rf-0.53.5}/.github/workflows/check-lint.yml +0 -0
  39. {ramses_rf-0.53.3 → ramses_rf-0.53.5}/.github/workflows/check-test.yml +0 -0
  40. {ramses_rf-0.53.3 → ramses_rf-0.53.5}/.github/workflows/check-type.yml +0 -0
  41. {ramses_rf-0.53.3 → ramses_rf-0.53.5}/.github/workflows/publish-hatch.yml +0 -0
  42. {ramses_rf-0.53.3 → ramses_rf-0.53.5}/.gitignore +0 -0
  43. {ramses_rf-0.53.3 → ramses_rf-0.53.5}/LICENSE +0 -0
  44. {ramses_rf-0.53.3 → ramses_rf-0.53.5}/README-developers.md +0 -0
  45. {ramses_rf-0.53.3 → ramses_rf-0.53.5}/README.md +0 -0
  46. {ramses_rf-0.53.3 → ramses_rf-0.53.5}/client.py +0 -0
  47. {ramses_rf-0.53.3 → ramses_rf-0.53.5}/docs/Makefile +0 -0
  48. {ramses_rf-0.53.3 → ramses_rf-0.53.5}/docs/make.bat +0 -0
  49. {ramses_rf-0.53.3 → ramses_rf-0.53.5}/docs/source/_static/CC-BY-NC-SA-4.0.txt +0 -0
  50. {ramses_rf-0.53.3 → ramses_rf-0.53.5}/docs/source/_static/ramses_rf_logo.png +0 -0
  51. {ramses_rf-0.53.3 → ramses_rf-0.53.5}/docs/source/binding_process.md +0 -0
  52. {ramses_rf-0.53.3 → ramses_rf-0.53.5}/docs/source/conf.py +0 -0
  53. {ramses_rf-0.53.3 → ramses_rf-0.53.5}/docs/source/glossary.rst +0 -0
  54. {ramses_rf-0.53.3 → ramses_rf-0.53.5}/docs/source/index.rst +0 -0
  55. {ramses_rf-0.53.3 → ramses_rf-0.53.5}/docs/source/modules.rst +0 -0
  56. {ramses_rf-0.53.3 → ramses_rf-0.53.5}/docs/source/ramses_cli.rst +0 -0
  57. {ramses_rf-0.53.3 → ramses_rf-0.53.5}/docs/source/ramses_rf.device.rst +0 -0
  58. {ramses_rf-0.53.3 → ramses_rf-0.53.5}/docs/source/ramses_rf.system.rst +0 -0
  59. {ramses_rf-0.53.3 → ramses_rf-0.53.5}/docs/source/ramses_tx.rst +0 -0
  60. {ramses_rf-0.53.3 → ramses_rf-0.53.5}/docs/source/usage.md +0 -0
  61. {ramses_rf-0.53.3 → ramses_rf-0.53.5}/misc/2411_parser.py +0 -0
  62. {ramses_rf-0.53.3 → ramses_rf-0.53.5}/misc/fingerprints.log +0 -0
  63. {ramses_rf-0.53.3 → ramses_rf-0.53.5}/misc/ser2net.yaml +0 -0
  64. {ramses_rf-0.53.3 → ramses_rf-0.53.5}/misc/ti_3410/notes.sh +0 -0
  65. {ramses_rf-0.53.3 → ramses_rf-0.53.5}/misc/ti_3410/ti_3410.fw +0 -0
  66. {ramses_rf-0.53.3 → ramses_rf-0.53.5}/ramses_cli/__init__.py +0 -0
  67. {ramses_rf-0.53.3 → ramses_rf-0.53.5}/ramses_cli/debug.py +0 -0
  68. {ramses_rf-0.53.3 → ramses_rf-0.53.5}/ramses_cli/discovery.py +0 -0
  69. {ramses_rf-0.53.3 → ramses_rf-0.53.5}/ramses_cli/py.typed +0 -0
  70. {ramses_rf-0.53.3 → ramses_rf-0.53.5}/ramses_cli/utils/cat_slow.py +0 -0
  71. {ramses_rf-0.53.3 → ramses_rf-0.53.5}/ramses_cli/utils/convert.py +0 -0
  72. {ramses_rf-0.53.3 → ramses_rf-0.53.5}/ramses_rf/__init__.py +0 -0
  73. {ramses_rf-0.53.3 → ramses_rf-0.53.5}/ramses_rf/binding_fsm.py +0 -0
  74. {ramses_rf-0.53.3 → ramses_rf-0.53.5}/ramses_rf/const.py +0 -0
  75. {ramses_rf-0.53.3 → ramses_rf-0.53.5}/ramses_rf/device/__init__.py +0 -0
  76. {ramses_rf-0.53.3 → ramses_rf-0.53.5}/ramses_rf/device/base.py +0 -0
  77. {ramses_rf-0.53.3 → ramses_rf-0.53.5}/ramses_rf/device/heat.py +0 -0
  78. {ramses_rf-0.53.3 → ramses_rf-0.53.5}/ramses_rf/device/hvac.py +0 -0
  79. {ramses_rf-0.53.3 → ramses_rf-0.53.5}/ramses_rf/dispatcher.py +0 -0
  80. {ramses_rf-0.53.3 → ramses_rf-0.53.5}/ramses_rf/exceptions.py +0 -0
  81. {ramses_rf-0.53.3 → ramses_rf-0.53.5}/ramses_rf/helpers.py +0 -0
  82. {ramses_rf-0.53.3 → ramses_rf-0.53.5}/ramses_rf/py.typed +0 -0
  83. {ramses_rf-0.53.3 → ramses_rf-0.53.5}/ramses_rf/schemas.py +0 -0
  84. {ramses_rf-0.53.3 → ramses_rf-0.53.5}/ramses_rf/system/__init__.py +0 -0
  85. {ramses_rf-0.53.3 → ramses_rf-0.53.5}/ramses_rf/system/faultlog.py +0 -0
  86. {ramses_rf-0.53.3 → ramses_rf-0.53.5}/ramses_rf/system/schedule.py +0 -0
  87. {ramses_rf-0.53.3 → ramses_rf-0.53.5}/ramses_rf/system/zones.py +0 -0
  88. {ramses_rf-0.53.3 → ramses_rf-0.53.5}/ramses_tx/address.py +0 -0
  89. {ramses_rf-0.53.3 → ramses_rf-0.53.5}/ramses_tx/command.py +0 -0
  90. {ramses_rf-0.53.3 → ramses_rf-0.53.5}/ramses_tx/exceptions.py +0 -0
  91. {ramses_rf-0.53.3 → ramses_rf-0.53.5}/ramses_tx/fingerprints.py +0 -0
  92. {ramses_rf-0.53.3 → ramses_rf-0.53.5}/ramses_tx/frame.py +0 -0
  93. {ramses_rf-0.53.3 → ramses_rf-0.53.5}/ramses_tx/helpers.py +0 -0
  94. {ramses_rf-0.53.3 → ramses_rf-0.53.5}/ramses_tx/message.py +0 -0
  95. {ramses_rf-0.53.3 → ramses_rf-0.53.5}/ramses_tx/opentherm.py +0 -0
  96. {ramses_rf-0.53.3 → ramses_rf-0.53.5}/ramses_tx/packet.py +0 -0
  97. {ramses_rf-0.53.3 → ramses_rf-0.53.5}/ramses_tx/protocol_fsm.py +0 -0
  98. {ramses_rf-0.53.3 → ramses_rf-0.53.5}/ramses_tx/py.typed +0 -0
  99. {ramses_rf-0.53.3 → ramses_rf-0.53.5}/ramses_tx/schemas.py +0 -0
  100. {ramses_rf-0.53.3 → ramses_rf-0.53.5}/ramses_tx/typed_dicts.py +0 -0
  101. {ramses_rf-0.53.3 → ramses_rf-0.53.5}/ramses_tx/typing.py +0 -0
  102. {ramses_rf-0.53.3 → ramses_rf-0.53.5}/requirements/requirements.txt +0 -0
  103. {ramses_rf-0.53.3 → ramses_rf-0.53.5}/requirements/requirements_docs.txt +0 -0
  104. {ramses_rf-0.53.3 → ramses_rf-0.53.5}/tests/deprecated/_test_apis_mock.py +0 -0
  105. {ramses_rf-0.53.3 → ramses_rf-0.53.5}/tests/deprecated/_test_mock_faultlog.py +0 -0
  106. {ramses_rf-0.53.3 → ramses_rf-0.53.5}/tests/deprecated/_test_mock_schedule.py +0 -0
  107. {ramses_rf-0.53.3 → ramses_rf-0.53.5}/tests/deprecated/_test_packets_bad.py +0 -0
  108. {ramses_rf-0.53.3 → ramses_rf-0.53.5}/tests/deprecated/_test_performance_WIP.py +0 -0
  109. {ramses_rf-0.53.3 → ramses_rf-0.53.5}/tests/deprecated/_test_state_mgt.py +0 -0
  110. {ramses_rf-0.53.3 → ramses_rf-0.53.5}/tests/deprecated/mocked_devices/__init__.py +0 -0
  111. {ramses_rf-0.53.3 → ramses_rf-0.53.5}/tests/deprecated/mocked_devices/command.py +0 -0
  112. {ramses_rf-0.53.3 → ramses_rf-0.53.5}/tests/deprecated/mocked_devices/const.py +0 -0
  113. {ramses_rf-0.53.3 → ramses_rf-0.53.5}/tests/deprecated/mocked_devices/device_heat.py +0 -0
  114. {ramses_rf-0.53.3 → ramses_rf-0.53.5}/tests/deprecated/mocked_devices/device_hvac.py +0 -0
  115. {ramses_rf-0.53.3 → ramses_rf-0.53.5}/tests/deprecated/mocked_devices/transport.py +0 -0
  116. {ramses_rf-0.53.3 → ramses_rf-0.53.5}/tests/test_HA_MQTT/test_transport_callback.py +0 -0
  117. {ramses_rf-0.53.3 → ramses_rf-0.53.5}/tests/tests/__init__.py +0 -0
  118. {ramses_rf-0.53.3 → ramses_rf-0.53.5}/tests/tests/bindings/heat/ctl_bdr_91t.log +0 -0
  119. {ramses_rf-0.53.3 → ramses_rf-0.53.5}/tests/tests/bindings/heat/dts_ctl_sensor.log +0 -0
  120. {ramses_rf-0.53.3 → ramses_rf-0.53.5}/tests/tests/bindings/heat/hcw_ctl_sensor.log +0 -0
  121. {ramses_rf-0.53.3 → ramses_rf-0.53.5}/tests/tests/bindings/heat/rnd_ctl_sensor.log +0 -0
  122. {ramses_rf-0.53.3 → ramses_rf-0.53.5}/tests/tests/bindings/heat/rnd_ctl_sensor.yaml +0 -0
  123. {ramses_rf-0.53.3 → ramses_rf-0.53.5}/tests/tests/bindings/heat/trv_ctl.log +0 -0
  124. {ramses_rf-0.53.3 → ramses_rf-0.53.5}/tests/tests/bindings/hvac/co2_fan_itho.json +0 -0
  125. {ramses_rf-0.53.3 → ramses_rf-0.53.5}/tests/tests/bindings/hvac/co2_fan_itho.log +0 -0
  126. {ramses_rf-0.53.3 → ramses_rf-0.53.5}/tests/tests/bindings/hvac/co2_fan_itho.yaml +0 -0
  127. {ramses_rf-0.53.3 → ramses_rf-0.53.5}/tests/tests/bindings/hvac/dis_fan_orcon.json +0 -0
  128. {ramses_rf-0.53.3 → ramses_rf-0.53.5}/tests/tests/bindings/hvac/dis_fan_orcon.log +0 -0
  129. {ramses_rf-0.53.3 → ramses_rf-0.53.5}/tests/tests/bindings/hvac/rem_fan_climarad.log +0 -0
  130. {ramses_rf-0.53.3 → ramses_rf-0.53.5}/tests/tests/bindings/hvac/rem_fan_nuaire.json +0 -0
  131. {ramses_rf-0.53.3 → ramses_rf-0.53.5}/tests/tests/bindings/hvac/rem_fan_nuaire.log +0 -0
  132. {ramses_rf-0.53.3 → ramses_rf-0.53.5}/tests/tests/bindings/hvac/rem_fan_nuaire.yaml +0 -0
  133. {ramses_rf-0.53.3 → ramses_rf-0.53.5}/tests/tests/bindings/hvac/rem_fan_vasco.log +0 -0
  134. {ramses_rf-0.53.3 → ramses_rf-0.53.5}/tests/tests/bindings/hvac/rem_fan_ventura.log +0 -0
  135. {ramses_rf-0.53.3 → ramses_rf-0.53.5}/tests/tests/devices/device_02.log +0 -0
  136. {ramses_rf-0.53.3 → ramses_rf-0.53.5}/tests/tests/devices/device_04.log +0 -0
  137. {ramses_rf-0.53.3 → ramses_rf-0.53.5}/tests/tests/devices/device_10.log +0 -0
  138. {ramses_rf-0.53.3 → ramses_rf-0.53.5}/tests/tests/devices/device_13.log +0 -0
  139. {ramses_rf-0.53.3 → ramses_rf-0.53.5}/tests/tests/devices/device_22.log +0 -0
  140. {ramses_rf-0.53.3 → ramses_rf-0.53.5}/tests/tests/eavesdrop_dev_class/hvac/known_list_eavesdrop_off.json +0 -0
  141. {ramses_rf-0.53.3 → ramses_rf-0.53.5}/tests/tests/eavesdrop_dev_class/hvac/known_list_eavesdrop_on.json +0 -0
  142. {ramses_rf-0.53.3 → ramses_rf-0.53.5}/tests/tests/eavesdrop_dev_class/hvac/packet.log +0 -0
  143. {ramses_rf-0.53.3 → ramses_rf-0.53.5}/tests/tests/eavesdrop_schema/_trv_actuator_long/packet.log +0 -0
  144. {ramses_rf-0.53.3 → ramses_rf-0.53.5}/tests/tests/eavesdrop_schema/_trv_actuator_long/schema_eavesdrop_off.json +0 -0
  145. {ramses_rf-0.53.3 → ramses_rf-0.53.5}/tests/tests/eavesdrop_schema/_trv_actuator_long/schema_eavesdrop_on.json +0 -0
  146. {ramses_rf-0.53.3 → ramses_rf-0.53.5}/tests/tests/eavesdrop_schema/_trv_actuator_mixed/packet.log +0 -0
  147. {ramses_rf-0.53.3 → ramses_rf-0.53.5}/tests/tests/eavesdrop_schema/_trv_actuator_mixed/schema_eavesdrop_off.json +0 -0
  148. {ramses_rf-0.53.3 → ramses_rf-0.53.5}/tests/tests/eavesdrop_schema/_trv_actuator_mixed/schema_eavesdrop_on.json +0 -0
  149. {ramses_rf-0.53.3 → ramses_rf-0.53.5}/tests/tests/eavesdrop_schema/_ufh_circuits/packet.log +0 -0
  150. {ramses_rf-0.53.3 → ramses_rf-0.53.5}/tests/tests/eavesdrop_schema/_ufh_circuits/schema_eavesdrop_off.json +0 -0
  151. {ramses_rf-0.53.3 → ramses_rf-0.53.5}/tests/tests/eavesdrop_schema/_ufh_circuits/schema_eavesdrop_on.json +0 -0
  152. {ramses_rf-0.53.3 → ramses_rf-0.53.5}/tests/tests/eavesdrop_schema/app_cntrl/packet.log +0 -0
  153. {ramses_rf-0.53.3 → ramses_rf-0.53.5}/tests/tests/eavesdrop_schema/app_cntrl/schema_eavesdrop_off.json +0 -0
  154. {ramses_rf-0.53.3 → ramses_rf-0.53.5}/tests/tests/eavesdrop_schema/app_cntrl/schema_eavesdrop_on.json +0 -0
  155. {ramses_rf-0.53.3 → ramses_rf-0.53.5}/tests/tests/eavesdrop_schema/trv_actuators/packet.log +0 -0
  156. {ramses_rf-0.53.3 → ramses_rf-0.53.5}/tests/tests/eavesdrop_schema/trv_actuators/schema_eavesdrop_off.json +0 -0
  157. {ramses_rf-0.53.3 → ramses_rf-0.53.5}/tests/tests/eavesdrop_schema/trv_actuators/schema_eavesdrop_on.json +0 -0
  158. {ramses_rf-0.53.3 → ramses_rf-0.53.5}/tests/tests/eavesdrop_schema/zone_sensors_000/packet.log +0 -0
  159. {ramses_rf-0.53.3 → ramses_rf-0.53.5}/tests/tests/eavesdrop_schema/zone_sensors_000/schema_eavesdrop_off.json +0 -0
  160. {ramses_rf-0.53.3 → ramses_rf-0.53.5}/tests/tests/eavesdrop_schema/zone_sensors_000/schema_eavesdrop_on.json +0 -0
  161. {ramses_rf-0.53.3 → ramses_rf-0.53.5}/tests/tests/eavesdrop_schema/zone_sensors_001/packet.log +0 -0
  162. {ramses_rf-0.53.3 → ramses_rf-0.53.5}/tests/tests/eavesdrop_schema/zone_sensors_001/schema_eavesdrop_off.json +0 -0
  163. {ramses_rf-0.53.3 → ramses_rf-0.53.5}/tests/tests/eavesdrop_schema/zone_sensors_001/schema_eavesdrop_on.json +0 -0
  164. {ramses_rf-0.53.3 → ramses_rf-0.53.5}/tests/tests/eavesdrop_schema/zone_sensors_002/packet.log +0 -0
  165. {ramses_rf-0.53.3 → ramses_rf-0.53.5}/tests/tests/eavesdrop_schema/zone_sensors_002/schema_eavesdrop_off.json +0 -0
  166. {ramses_rf-0.53.3 → ramses_rf-0.53.5}/tests/tests/eavesdrop_schema/zone_sensors_002/schema_eavesdrop_on.json +0 -0
  167. {ramses_rf-0.53.3 → ramses_rf-0.53.5}/tests/tests/eavesdrop_schema/zone_sensors_003/packet.log +0 -0
  168. {ramses_rf-0.53.3 → ramses_rf-0.53.5}/tests/tests/eavesdrop_schema/zone_sensors_003/schema_eavesdrop_off.json +0 -0
  169. {ramses_rf-0.53.3 → ramses_rf-0.53.5}/tests/tests/eavesdrop_schema/zone_sensors_003/schema_eavesdrop_on.json +0 -0
  170. {ramses_rf-0.53.3 → ramses_rf-0.53.5}/tests/tests/eavesdrop_schema/zone_sensors_004/packet.log +0 -0
  171. {ramses_rf-0.53.3 → ramses_rf-0.53.5}/tests/tests/eavesdrop_schema/zone_sensors_004/schema_eavesdrop_off.json +0 -0
  172. {ramses_rf-0.53.3 → ramses_rf-0.53.5}/tests/tests/eavesdrop_schema/zone_sensors_004/schema_eavesdrop_on.json +0 -0
  173. {ramses_rf-0.53.3 → ramses_rf-0.53.5}/tests/tests/fingerprints/10e0_xxxx.log +0 -0
  174. {ramses_rf-0.53.3 → ramses_rf-0.53.5}/tests/tests/fingerprints/_gather.sh +0 -0
  175. {ramses_rf-0.53.3 → ramses_rf-0.53.5}/tests/tests/fingerprints/heat/01_EvoTouch_Colour.log +0 -0
  176. {ramses_rf-0.53.3 → ramses_rf-0.53.5}/tests/tests/fingerprints/heat/01_Evo_Color.log +0 -0
  177. {ramses_rf-0.53.3 → ramses_rf-0.53.5}/tests/tests/fingerprints/heat/01_IONA_RAI_Prototype.log +0 -0
  178. {ramses_rf-0.53.3 → ramses_rf-0.53.5}/tests/tests/fingerprints/heat/02_HCE80_V3.10_061117..log +0 -0
  179. {ramses_rf-0.53.3 → ramses_rf-0.53.5}/tests/tests/fingerprints/heat/04_HR92 Radiator Ctrl_.log +0 -0
  180. {ramses_rf-0.53.3 → ramses_rf-0.53.5}/tests/tests/fingerprints/heat/08_Jasper_EIM.log +0 -0
  181. {ramses_rf-0.53.3 → ramses_rf-0.53.5}/tests/tests/fingerprints/heat/10_R8810A_Bridge.log +0 -0
  182. {ramses_rf-0.53.3 → ramses_rf-0.53.5}/tests/tests/fingerprints/heat/10_R8820.log +0 -0
  183. {ramses_rf-0.53.3 → ramses_rf-0.53.5}/tests/tests/fingerprints/heat/30_Internet_Gateway.log +0 -0
  184. {ramses_rf-0.53.3 → ramses_rf-0.53.5}/tests/tests/fingerprints/heat/31_Jasper_Stat_TXXX.log +0 -0
  185. {ramses_rf-0.53.3 → ramses_rf-0.53.5}/tests/tests/fingerprints/heat/34_T87RF2025.log +0 -0
  186. {ramses_rf-0.53.3 → ramses_rf-0.53.5}/tests/tests/fingerprints/hvac/18_BRDG-02A55.log +0 -0
  187. {ramses_rf-0.53.3 → ramses_rf-0.53.5}/tests/tests/fingerprints/hvac/18_HRA82.log +0 -0
  188. {ramses_rf-0.53.3 → ramses_rf-0.53.5}/tests/tests/fingerprints/hvac/20.log +0 -0
  189. {ramses_rf-0.53.3 → ramses_rf-0.53.5}/tests/tests/fingerprints/hvac/21_CCU-12T20.log +0 -0
  190. {ramses_rf-0.53.3 → ramses_rf-0.53.5}/tests/tests/fingerprints/hvac/29_VMC-07RP01.log +0 -0
  191. {ramses_rf-0.53.3 → ramses_rf-0.53.5}/tests/tests/fingerprints/hvac/29_VMC-15RP01.log +0 -0
  192. {ramses_rf-0.53.3 → ramses_rf-0.53.5}/tests/tests/fingerprints/hvac/29_VMC-17RP01.log +0 -0
  193. {ramses_rf-0.53.3 → ramses_rf-0.53.5}/tests/tests/fingerprints/hvac/29_VMN-07LM01.log +0 -0
  194. {ramses_rf-0.53.3 → ramses_rf-0.53.5}/tests/tests/fingerprints/hvac/29_VMN-15LF01.log +0 -0
  195. {ramses_rf-0.53.3 → ramses_rf-0.53.5}/tests/tests/fingerprints/hvac/29_VMN-17LMP01.log +0 -0
  196. {ramses_rf-0.53.3 → ramses_rf-0.53.5}/tests/tests/fingerprints/hvac/29_VMS-15C16.log +0 -0
  197. {ramses_rf-0.53.3 → ramses_rf-0.53.5}/tests/tests/fingerprints/hvac/29_VMS-17HB01.log +0 -0
  198. {ramses_rf-0.53.3 → ramses_rf-0.53.5}/tests/tests/fingerprints/hvac/30_BRDG-02EM23.log +0 -0
  199. {ramses_rf-0.53.3 → ramses_rf-0.53.5}/tests/tests/fingerprints/hvac/30_BRDG-02JAS01.log +0 -0
  200. {ramses_rf-0.53.3 → ramses_rf-0.53.5}/tests/tests/fingerprints/hvac/32_VMC-15RPS34.log +0 -0
  201. {ramses_rf-0.53.3 → ramses_rf-0.53.5}/tests/tests/fingerprints/hvac/32_VMD-15RMS64.log +0 -0
  202. {ramses_rf-0.53.3 → ramses_rf-0.53.5}/tests/tests/fingerprints/hvac/32_VMD-15RMS86.log +0 -0
  203. {ramses_rf-0.53.3 → ramses_rf-0.53.5}/tests/tests/fingerprints/hvac/32_VMD-17RPS01.log +0 -0
  204. {ramses_rf-0.53.3 → ramses_rf-0.53.5}/tests/tests/fingerprints/hvac/32_VMN-23LM33.log +0 -0
  205. {ramses_rf-0.53.3 → ramses_rf-0.53.5}/tests/tests/fingerprints/hvac/32_VMN-23LMH23.log +0 -0
  206. {ramses_rf-0.53.3 → ramses_rf-0.53.5}/tests/tests/fingerprints/hvac/32_VMS-15CM17.log +0 -0
  207. {ramses_rf-0.53.3 → ramses_rf-0.53.5}/tests/tests/fingerprints/hvac/32_VMS-23C33.log +0 -0
  208. {ramses_rf-0.53.3 → ramses_rf-0.53.5}/tests/tests/fingerprints/hvac/32_VMS-23HB33.log +0 -0
  209. {ramses_rf-0.53.3 → ramses_rf-0.53.5}/tests/tests/fingerprints/hvac/32_VMZ-15V13.log +0 -0
  210. {ramses_rf-0.53.3 → ramses_rf-0.53.5}/tests/tests/fingerprints/hvac/37_VMD-07RPS13.log +0 -0
  211. {ramses_rf-0.53.3 → ramses_rf-0.53.5}/tests/tests/fingerprints/hvac/37_VMI-15MC01log +0 -0
  212. {ramses_rf-0.53.3 → ramses_rf-0.53.5}/tests/tests/fingerprints/hvac/37_VMI-15WSJ53.log +0 -0
  213. {ramses_rf-0.53.3 → ramses_rf-0.53.5}/tests/tests/fingerprints/hvac/37_VMS-02J52.log +0 -0
  214. {ramses_rf-0.53.3 → ramses_rf-0.53.5}/tests/tests/fingerprints/hvac/37_VMS-12C39.log +0 -0
  215. {ramses_rf-0.53.3 → ramses_rf-0.53.5}/tests/tests/fingerprints/hvac/99_CVE-RF.log +0 -0
  216. {ramses_rf-0.53.3 → ramses_rf-0.53.5}/tests/tests/fingerprints/hvac/99_VMS-17C01.log +0 -0
  217. {ramses_rf-0.53.3 → ramses_rf-0.53.5}/tests/tests/logger/packet_in.log +0 -0
  218. {ramses_rf-0.53.3 → ramses_rf-0.53.5}/tests/tests/logger/packet_out.log +0 -0
  219. {ramses_rf-0.53.3 → ramses_rf-0.53.5}/tests/tests/logs/pkts_bad_000.log +0 -0
  220. {ramses_rf-0.53.3 → ramses_rf-0.53.5}/tests/tests/logs/pkts_tba_000.log +0 -0
  221. {ramses_rf-0.53.3 → ramses_rf-0.53.5}/tests/tests/logs/system_cache.json +0 -0
  222. {ramses_rf-0.53.3 → ramses_rf-0.53.5}/tests/tests/parser_helpers/pkt_addr_set.log +0 -0
  223. {ramses_rf-0.53.3 → ramses_rf-0.53.5}/tests/tests/parser_helpers/pkt_dev_class.log +0 -0
  224. {ramses_rf-0.53.3 → ramses_rf-0.53.5}/tests/tests/parsers/code_0001_wip.log +0 -0
  225. {ramses_rf-0.53.3 → ramses_rf-0.53.5}/tests/tests/parsers/code_0002.log +0 -0
  226. {ramses_rf-0.53.3 → ramses_rf-0.53.5}/tests/tests/parsers/code_0004_wip.log +0 -0
  227. {ramses_rf-0.53.3 → ramses_rf-0.53.5}/tests/tests/parsers/code_0005.log +0 -0
  228. {ramses_rf-0.53.3 → ramses_rf-0.53.5}/tests/tests/parsers/code_0006.log +0 -0
  229. {ramses_rf-0.53.3 → ramses_rf-0.53.5}/tests/tests/parsers/code_0008.log +0 -0
  230. {ramses_rf-0.53.3 → ramses_rf-0.53.5}/tests/tests/parsers/code_0009.log +0 -0
  231. {ramses_rf-0.53.3 → ramses_rf-0.53.5}/tests/tests/parsers/code_000a.log +0 -0
  232. {ramses_rf-0.53.3 → ramses_rf-0.53.5}/tests/tests/parsers/code_000c.log +0 -0
  233. {ramses_rf-0.53.3 → ramses_rf-0.53.5}/tests/tests/parsers/code_000e.log +0 -0
  234. {ramses_rf-0.53.3 → ramses_rf-0.53.5}/tests/tests/parsers/code_01ff_wip.log +0 -0
  235. {ramses_rf-0.53.3 → ramses_rf-0.53.5}/tests/tests/parsers/code_0418.log +0 -0
  236. {ramses_rf-0.53.3 → ramses_rf-0.53.5}/tests/tests/parsers/code_042f.log +0 -0
  237. {ramses_rf-0.53.3 → ramses_rf-0.53.5}/tests/tests/parsers/code_1030.log +0 -0
  238. {ramses_rf-0.53.3 → ramses_rf-0.53.5}/tests/tests/parsers/code_1060.log +0 -0
  239. {ramses_rf-0.53.3 → ramses_rf-0.53.5}/tests/tests/parsers/code_10d0.log +0 -0
  240. {ramses_rf-0.53.3 → ramses_rf-0.53.5}/tests/tests/parsers/code_10e0.log +0 -0
  241. {ramses_rf-0.53.3 → ramses_rf-0.53.5}/tests/tests/parsers/code_1260.log +0 -0
  242. {ramses_rf-0.53.3 → ramses_rf-0.53.5}/tests/tests/parsers/code_1298.log +0 -0
  243. {ramses_rf-0.53.3 → ramses_rf-0.53.5}/tests/tests/parsers/code_12a0.log +0 -0
  244. {ramses_rf-0.53.3 → ramses_rf-0.53.5}/tests/tests/parsers/code_12c0.log +0 -0
  245. {ramses_rf-0.53.3 → ramses_rf-0.53.5}/tests/tests/parsers/code_1300.log +0 -0
  246. {ramses_rf-0.53.3 → ramses_rf-0.53.5}/tests/tests/parsers/code_1f09.log +0 -0
  247. {ramses_rf-0.53.3 → ramses_rf-0.53.5}/tests/tests/parsers/code_1fc9.log +0 -0
  248. {ramses_rf-0.53.3 → ramses_rf-0.53.5}/tests/tests/parsers/code_1fd4.log +0 -0
  249. {ramses_rf-0.53.3 → ramses_rf-0.53.5}/tests/tests/parsers/code_22c9.log +0 -0
  250. {ramses_rf-0.53.3 → ramses_rf-0.53.5}/tests/tests/parsers/code_22d0.log +0 -0
  251. {ramses_rf-0.53.3 → ramses_rf-0.53.5}/tests/tests/parsers/code_22d9.log +0 -0
  252. {ramses_rf-0.53.3 → ramses_rf-0.53.5}/tests/tests/parsers/code_22e0.log +0 -0
  253. {ramses_rf-0.53.3 → ramses_rf-0.53.5}/tests/tests/parsers/code_22e5.log +0 -0
  254. {ramses_rf-0.53.3 → ramses_rf-0.53.5}/tests/tests/parsers/code_22e9.log +0 -0
  255. {ramses_rf-0.53.3 → ramses_rf-0.53.5}/tests/tests/parsers/code_22f1.log +0 -0
  256. {ramses_rf-0.53.3 → ramses_rf-0.53.5}/tests/tests/parsers/code_22f2.log +0 -0
  257. {ramses_rf-0.53.3 → ramses_rf-0.53.5}/tests/tests/parsers/code_22f3.log +0 -0
  258. {ramses_rf-0.53.3 → ramses_rf-0.53.5}/tests/tests/parsers/code_22f4.log +0 -0
  259. {ramses_rf-0.53.3 → ramses_rf-0.53.5}/tests/tests/parsers/code_22f7.log +0 -0
  260. {ramses_rf-0.53.3 → ramses_rf-0.53.5}/tests/tests/parsers/code_2309.log +0 -0
  261. {ramses_rf-0.53.3 → ramses_rf-0.53.5}/tests/tests/parsers/code_2349.log +0 -0
  262. {ramses_rf-0.53.3 → ramses_rf-0.53.5}/tests/tests/parsers/code_2411_wip.log +0 -0
  263. {ramses_rf-0.53.3 → ramses_rf-0.53.5}/tests/tests/parsers/code_2e04.log +0 -0
  264. {ramses_rf-0.53.3 → ramses_rf-0.53.5}/tests/tests/parsers/code_2e10_wip.log +0 -0
  265. {ramses_rf-0.53.3 → ramses_rf-0.53.5}/tests/tests/parsers/code_30c9.log +0 -0
  266. {ramses_rf-0.53.3 → ramses_rf-0.53.5}/tests/tests/parsers/code_3110_wip.log +0 -0
  267. {ramses_rf-0.53.3 → ramses_rf-0.53.5}/tests/tests/parsers/code_3120.log +0 -0
  268. {ramses_rf-0.53.3 → ramses_rf-0.53.5}/tests/tests/parsers/code_313e_wip.log +0 -0
  269. {ramses_rf-0.53.3 → ramses_rf-0.53.5}/tests/tests/parsers/code_3150.log +0 -0
  270. {ramses_rf-0.53.3 → ramses_rf-0.53.5}/tests/tests/parsers/code_31d9.log +0 -0
  271. {ramses_rf-0.53.3 → ramses_rf-0.53.5}/tests/tests/parsers/code_31da.log +0 -0
  272. {ramses_rf-0.53.3 → ramses_rf-0.53.5}/tests/tests/parsers/code_3200.log +0 -0
  273. {ramses_rf-0.53.3 → ramses_rf-0.53.5}/tests/tests/parsers/code_3210.log +0 -0
  274. {ramses_rf-0.53.3 → ramses_rf-0.53.5}/tests/tests/parsers/code_3220.log +0 -0
  275. {ramses_rf-0.53.3 → ramses_rf-0.53.5}/tests/tests/parsers/code_3222.log +0 -0
  276. {ramses_rf-0.53.3 → ramses_rf-0.53.5}/tests/tests/parsers/code_3ef0_wip.log +0 -0
  277. {ramses_rf-0.53.3 → ramses_rf-0.53.5}/tests/tests/parsers/code_3ef1_wip.log +0 -0
  278. {ramses_rf-0.53.3 → ramses_rf-0.53.5}/tests/tests/parsers/code_4e01.log +0 -0
  279. {ramses_rf-0.53.3 → ramses_rf-0.53.5}/tests/tests/parsers/code_4e02.log +0 -0
  280. {ramses_rf-0.53.3 → ramses_rf-0.53.5}/tests/tests/parsers/code_4e04.log +0 -0
  281. {ramses_rf-0.53.3 → ramses_rf-0.53.5}/tests/tests/parsers/code_4e15.log +0 -0
  282. {ramses_rf-0.53.3 → ramses_rf-0.53.5}/tests/tests/schedules/_sched_002/packet.log +0 -0
  283. {ramses_rf-0.53.3 → ramses_rf-0.53.5}/tests/tests/schedules/_sched_002/schedule.json +0 -0
  284. {ramses_rf-0.53.3 → ramses_rf-0.53.5}/tests/tests/schedules/sched_001/packet.log +0 -0
  285. {ramses_rf-0.53.3 → ramses_rf-0.53.5}/tests/tests/schedules/sched_001/schedule.json +0 -0
  286. {ramses_rf-0.53.3 → ramses_rf-0.53.5}/tests/tests/schedules/sched_dhw/packet.log +0 -0
  287. {ramses_rf-0.53.3 → ramses_rf-0.53.5}/tests/tests/schedules/sched_dhw/schedule.json +0 -0
  288. {ramses_rf-0.53.3 → ramses_rf-0.53.5}/tests/tests/schemas/jsn_files/schema_100.json +0 -0
  289. {ramses_rf-0.53.3 → ramses_rf-0.53.5}/tests/tests/schemas/jsn_files/schema_101.json +0 -0
  290. {ramses_rf-0.53.3 → ramses_rf-0.53.5}/tests/tests/schemas/jsn_files/schema_102.json +0 -0
  291. {ramses_rf-0.53.3 → ramses_rf-0.53.5}/tests/tests/schemas/jsn_files/schema_103.json +0 -0
  292. {ramses_rf-0.53.3 → ramses_rf-0.53.5}/tests/tests/schemas/jsn_files/schema_104.json +0 -0
  293. {ramses_rf-0.53.3 → ramses_rf-0.53.5}/tests/tests/schemas/jsn_files/schema_105.json +0 -0
  294. {ramses_rf-0.53.3 → ramses_rf-0.53.5}/tests/tests/schemas/jsn_files/schema_108.json +0 -0
  295. {ramses_rf-0.53.3 → ramses_rf-0.53.5}/tests/tests/schemas/log_files/schema_000.json +0 -0
  296. {ramses_rf-0.53.3 → ramses_rf-0.53.5}/tests/tests/schemas/log_files/schema_000.log +0 -0
  297. {ramses_rf-0.53.3 → ramses_rf-0.53.5}/tests/tests/schemas/log_files/schema_001.json +0 -0
  298. {ramses_rf-0.53.3 → ramses_rf-0.53.5}/tests/tests/schemas/log_files/schema_001.log +0 -0
  299. {ramses_rf-0.53.3 → ramses_rf-0.53.5}/tests/tests/schemas/log_files/schema_002.json +0 -0
  300. {ramses_rf-0.53.3 → ramses_rf-0.53.5}/tests/tests/schemas/log_files/schema_002.log +0 -0
  301. {ramses_rf-0.53.3 → ramses_rf-0.53.5}/tests/tests/schemas/log_files/schema_010.json +0 -0
  302. {ramses_rf-0.53.3 → ramses_rf-0.53.5}/tests/tests/schemas/log_files/schema_010.log +0 -0
  303. {ramses_rf-0.53.3 → ramses_rf-0.53.5}/tests/tests/schemas/log_files/schema_011.json +0 -0
  304. {ramses_rf-0.53.3 → ramses_rf-0.53.5}/tests/tests/schemas/log_files/schema_011.log +0 -0
  305. {ramses_rf-0.53.3 → ramses_rf-0.53.5}/tests/tests/schemas/log_files/schema_012.json +0 -0
  306. {ramses_rf-0.53.3 → ramses_rf-0.53.5}/tests/tests/schemas/log_files/schema_012.log +0 -0
  307. {ramses_rf-0.53.3 → ramses_rf-0.53.5}/tests/tests/schemas/log_files/schema_013.json +0 -0
  308. {ramses_rf-0.53.3 → ramses_rf-0.53.5}/tests/tests/schemas/log_files/schema_013.log +0 -0
  309. {ramses_rf-0.53.3 → ramses_rf-0.53.5}/tests/tests/schemas/log_files/schema_014.json +0 -0
  310. {ramses_rf-0.53.3 → ramses_rf-0.53.5}/tests/tests/schemas/log_files/schema_014.log +0 -0
  311. {ramses_rf-0.53.3 → ramses_rf-0.53.5}/tests/tests/schemas/log_files/schema_300.json +0 -0
  312. {ramses_rf-0.53.3 → ramses_rf-0.53.5}/tests/tests/schemas/log_files/schema_300.log +0 -0
  313. {ramses_rf-0.53.3 → ramses_rf-0.53.5}/tests/tests/schemas/log_files/schema_301.json +0 -0
  314. {ramses_rf-0.53.3 → ramses_rf-0.53.5}/tests/tests/schemas/log_files/schema_301.log +0 -0
  315. {ramses_rf-0.53.3 → ramses_rf-0.53.5}/tests/tests/schemas/log_files/schema_302.json +0 -0
  316. {ramses_rf-0.53.3 → ramses_rf-0.53.5}/tests/tests/schemas/log_files/schema_302.log +0 -0
  317. {ramses_rf-0.53.3 → ramses_rf-0.53.5}/tests/tests/schemas/log_files/schema_303.json +0 -0
  318. {ramses_rf-0.53.3 → ramses_rf-0.53.5}/tests/tests/schemas/log_files/schema_303.log +0 -0
  319. {ramses_rf-0.53.3 → ramses_rf-0.53.5}/tests/tests/schemas/log_files/schema_304.json +0 -0
  320. {ramses_rf-0.53.3 → ramses_rf-0.53.5}/tests/tests/schemas/log_files/schema_304.log +0 -0
  321. {ramses_rf-0.53.3 → ramses_rf-0.53.5}/tests/tests/schemas/log_files/schema_310.json +0 -0
  322. {ramses_rf-0.53.3 → ramses_rf-0.53.5}/tests/tests/schemas/log_files/schema_310.log +0 -0
  323. {ramses_rf-0.53.3 → ramses_rf-0.53.5}/tests/tests/systems/_heat_trv_00/config.json +0 -0
  324. {ramses_rf-0.53.3 → ramses_rf-0.53.5}/tests/tests/systems/_heat_trv_00/packet.log +0 -0
  325. {ramses_rf-0.53.3 → ramses_rf-0.53.5}/tests/tests/systems/_heat_trv_00/schema.json +0 -0
  326. {ramses_rf-0.53.3 → ramses_rf-0.53.5}/tests/tests/systems/_hvac_nuaire/config.json +0 -0
  327. {ramses_rf-0.53.3 → ramses_rf-0.53.5}/tests/tests/systems/_hvac_nuaire/known_list.json +0 -0
  328. {ramses_rf-0.53.3 → ramses_rf-0.53.5}/tests/tests/systems/_hvac_nuaire/packet.log +0 -0
  329. {ramses_rf-0.53.3 → ramses_rf-0.53.5}/tests/tests/systems/_hvac_nuaire/schema.json +0 -0
  330. {ramses_rf-0.53.3 → ramses_rf-0.53.5}/tests/tests/systems/_hvac_nuaire/status.json +0 -0
  331. {ramses_rf-0.53.3 → ramses_rf-0.53.5}/tests/tests/systems/heat_otb_00/config.json +0 -0
  332. {ramses_rf-0.53.3 → ramses_rf-0.53.5}/tests/tests/systems/heat_otb_00/packet.log +0 -0
  333. {ramses_rf-0.53.3 → ramses_rf-0.53.5}/tests/tests/systems/heat_otb_00/schema.json +0 -0
  334. {ramses_rf-0.53.3 → ramses_rf-0.53.5}/tests/tests/systems/heat_simple/packet.log +0 -0
  335. {ramses_rf-0.53.3 → ramses_rf-0.53.5}/tests/tests/systems/heat_simple/schema.json +0 -0
  336. {ramses_rf-0.53.3 → ramses_rf-0.53.5}/tests/tests/systems/heat_ufc_00/config.json +0 -0
  337. {ramses_rf-0.53.3 → ramses_rf-0.53.5}/tests/tests/systems/heat_ufc_00/packet.log +0 -0
  338. {ramses_rf-0.53.3 → ramses_rf-0.53.5}/tests/tests/systems/heat_ufc_01/packet.log +0 -0
  339. {ramses_rf-0.53.3 → ramses_rf-0.53.5}/tests/tests/systems/heat_zxdavb/config.json +0 -0
  340. {ramses_rf-0.53.3 → ramses_rf-0.53.5}/tests/tests/systems/heat_zxdavb/known_list.json +0 -0
  341. {ramses_rf-0.53.3 → ramses_rf-0.53.5}/tests/tests/systems/heat_zxdavb/packet.log +0 -0
  342. {ramses_rf-0.53.3 → ramses_rf-0.53.5}/tests/tests/systems/heat_zxdavb/schema.json +0 -0
  343. {ramses_rf-0.53.3 → ramses_rf-0.53.5}/tests/tests/test_api_faultlog.py +0 -0
  344. {ramses_rf-0.53.3 → ramses_rf-0.53.5}/tests/tests/test_api_schedule.py +0 -0
  345. {ramses_rf-0.53.3 → ramses_rf-0.53.5}/tests/tests/test_apis_binding.py +0 -0
  346. {ramses_rf-0.53.3 → ramses_rf-0.53.5}/tests/tests/test_apis_common.py +0 -0
  347. {ramses_rf-0.53.3 → ramses_rf-0.53.5}/tests/tests/test_apis_heat.py +0 -0
  348. {ramses_rf-0.53.3 → ramses_rf-0.53.5}/tests/tests/test_apis_hvac.py +0 -0
  349. {ramses_rf-0.53.3 → ramses_rf-0.53.5}/tests/tests/test_cli_transport_factory.py +0 -0
  350. {ramses_rf-0.53.3 → ramses_rf-0.53.5}/tests/tests/test_devices.py +0 -0
  351. {ramses_rf-0.53.3 → ramses_rf-0.53.5}/tests/tests/test_eavesdrop_dev_class.py +0 -0
  352. {ramses_rf-0.53.3 → ramses_rf-0.53.5}/tests/tests/test_helpers.py +0 -0
  353. {ramses_rf-0.53.3 → ramses_rf-0.53.5}/tests/tests/test_parser_helpers.py +0 -0
  354. {ramses_rf-0.53.3 → ramses_rf-0.53.5}/tests/tests/test_parsers.py +0 -0
  355. {ramses_rf-0.53.3 → ramses_rf-0.53.5}/tests/tests/test_ramses_schema.py +0 -0
  356. {ramses_rf-0.53.3 → ramses_rf-0.53.5}/tests/tests/test_schema_bits.py +0 -0
  357. {ramses_rf-0.53.3 → ramses_rf-0.53.5}/tests/tests/test_storage.py +0 -0
  358. {ramses_rf-0.53.3 → ramses_rf-0.53.5}/tests/tests/test_vol_schemas.py +0 -0
  359. {ramses_rf-0.53.3 → ramses_rf-0.53.5}/tests/tests_cli/test_cli_utility.py +0 -0
  360. {ramses_rf-0.53.3 → ramses_rf-0.53.5}/tests/tests_cli/test_debug.py +0 -0
  361. {ramses_rf-0.53.3 → ramses_rf-0.53.5}/tests/tests_cli/test_discovery.py +0 -0
  362. {ramses_rf-0.53.3 → ramses_rf-0.53.5}/tests/tests_rf/__init__.py +0 -0
  363. {ramses_rf-0.53.3 → ramses_rf-0.53.5}/tests/tests_rf/configs/config_heat.json +0 -0
  364. {ramses_rf-0.53.3 → ramses_rf-0.53.5}/tests/tests_rf/configs/config_hvac.json +0 -0
  365. {ramses_rf-0.53.3 → ramses_rf-0.53.5}/tests/tests_rf/conftest.py +0 -0
  366. {ramses_rf-0.53.3 → ramses_rf-0.53.5}/tests/tests_rf/device/__init__.py +0 -0
  367. {ramses_rf-0.53.3 → ramses_rf-0.53.5}/tests/tests_rf/device/test_hvac_ventilator.py +0 -0
  368. {ramses_rf-0.53.3 → ramses_rf-0.53.5}/tests/tests_rf/logs/test_api_faultlog.log +0 -0
  369. {ramses_rf-0.53.3 → ramses_rf-0.53.5}/tests/tests_rf/test_api_faultlog.py +0 -0
  370. {ramses_rf-0.53.3 → ramses_rf-0.53.5}/tests/tests_rf/test_api_schedule.py +0 -0
  371. {ramses_rf-0.53.3 → ramses_rf-0.53.5}/tests/tests_rf/test_binding_fsm.py +0 -0
  372. {ramses_rf-0.53.3 → ramses_rf-0.53.5}/tests/tests_rf/test_create_stack.py +0 -0
  373. {ramses_rf-0.53.3 → ramses_rf-0.53.5}/tests/tests_rf/test_database.py +0 -0
  374. {ramses_rf-0.53.3 → ramses_rf-0.53.5}/tests/tests_rf/test_dispatcher.py +0 -0
  375. {ramses_rf-0.53.3 → ramses_rf-0.53.5}/tests/tests_rf/test_hgi_behaviors.py +0 -0
  376. {ramses_rf-0.53.3 → ramses_rf-0.53.5}/tests/tests_rf/test_use_regex.py +0 -0
  377. {ramses_rf-0.53.3 → ramses_rf-0.53.5}/tests/tests_rf/test_virt_network.py +0 -0
  378. {ramses_rf-0.53.3 → ramses_rf-0.53.5}/tests/tests_rf/test_virtual_rf.py +0 -0
  379. {ramses_rf-0.53.3 → ramses_rf-0.53.5}/tests/tests_rf/virtual_rf/__init__.py +0 -0
  380. {ramses_rf-0.53.3 → ramses_rf-0.53.5}/tests/tests_rf/virtual_rf/const.py +0 -0
  381. {ramses_rf-0.53.3 → ramses_rf-0.53.5}/tests/tests_rf/virtual_rf/helpers.py +0 -0
  382. {ramses_rf-0.53.3 → ramses_rf-0.53.5}/tests/tests_rf/virtual_rf/virtual_rf.py +0 -0
  383. {ramses_rf-0.53.3 → ramses_rf-0.53.5}/tests/tests_tx/__init__.py +0 -0
  384. {ramses_rf-0.53.3 → ramses_rf-0.53.5}/tests/tests_tx/test_command.py +0 -0
  385. {ramses_rf-0.53.3 → ramses_rf-0.53.5}/tests/tests_tx/test_const.py +0 -0
  386. {ramses_rf-0.53.3 → ramses_rf-0.53.5}/tests/wip/_test_eavesdrop_dhw_sensor.py +0 -0
  387. {ramses_rf-0.53.3 → ramses_rf-0.53.5}/tests/wip/_test_eavesdrop_htg_control.py +0 -0
  388. {ramses_rf-0.53.3 → ramses_rf-0.53.5}/tests/wip/_test_eavesdrop_ufc_circuits.py +0 -0
  389. {ramses_rf-0.53.3 → ramses_rf-0.53.5}/tests/wip/_test_eavesdrop_zone_sensors.py +0 -0
  390. {ramses_rf-0.53.3 → ramses_rf-0.53.5}/tests/wip/_test_eavesdrop_zone_type.py +0 -0
  391. {ramses_rf-0.53.3 → ramses_rf-0.53.5}/tests/wip/test_wip_cli.sh +0 -0
@@ -89,7 +89,7 @@ jobs:
89
89
  hide_complexity: true
90
90
  indicators: true
91
91
  output: both
92
- thresholds: '80 90'
92
+ thresholds: '80 95'
93
93
 
94
94
  - name: Add Coverage PR Comment
95
95
  # from: https://github.com/marketplace/actions/comment-pull-request
@@ -14,7 +14,7 @@ repos:
14
14
  # Run `python-typing-update` hook manually from time to time
15
15
  # to update python typing syntax.
16
16
  # Will require manual work, before submitting changes!
17
- # pre-commit run --hook-stage manual python-typing-update --all-files
17
+ # prek run --hook-stage manual python-typing-update --all-files
18
18
  - id: python-typing-update
19
19
  stages: [manual]
20
20
  args:
@@ -39,6 +39,10 @@ repos:
39
39
  hooks:
40
40
  - id: check-executables-have-shebangs
41
41
  # id: check-json # don't enable this one
42
+ # - id: no-commit-to-branch
43
+ # args:
44
+ # - --branch=master
45
+ # - --branch=stable
42
46
  - id: check-toml
43
47
  - id: check-yaml
44
48
  - id: debug-statements
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: ramses_rf
3
- Version: 0.53.3
3
+ Version: 0.53.5
4
4
  Summary: A stateful RAMSES-II protocol decoder & analyser.
5
5
  Project-URL: Homepage, https://github.com/ramses-rf/ramses_rf
6
6
  Project-URL: Bug Tracker, https://github.com/ramses-rf/ramses_rf/issues
@@ -99,6 +99,14 @@ ramses\_rf.schemas module
99
99
  :show-inheritance:
100
100
  :undoc-members:
101
101
 
102
+ ramses\_rf.storage module
103
+ -------------------------
104
+
105
+ .. automodule:: ramses_rf.storage
106
+ :members:
107
+ :show-inheritance:
108
+ :undoc-members:
109
+
102
110
  ramses\_rf.version module
103
111
  -------------------------
104
112
 
@@ -116,7 +116,7 @@
116
116
  "raise NotImplementedError",
117
117
  ]
118
118
  format = "text"
119
- fail_under = 75
119
+ fail_under = 80 # total cov now 83%
120
120
  ignore_errors = true
121
121
 
122
122
  [tool.coverage.html]
@@ -471,13 +471,8 @@ def print_results(gwy: Gateway, **kwargs: Any) -> None:
471
471
  system_id, _ = kwargs[GET_SCHED]
472
472
 
473
473
 
474
- def _save_state(gwy: Gateway) -> None:
475
- """Save the gateway state to files.
476
-
477
- :param gwy: The gateway instance.
478
- """
479
- schema, msgs = gwy.get_state()
480
-
474
+ def _write_state(schema: dict[str, Any], msgs: dict[str, str]) -> None:
475
+ """Write the state to the file system (blocking)."""
481
476
  with open("state_msgs.log", "w") as f:
482
477
  [f.write(f"{dtm} {pkt}\r\n") for dtm, pkt in msgs.items()] # if not m._expired
483
478
 
@@ -485,13 +480,22 @@ def _save_state(gwy: Gateway) -> None:
485
480
  f.write(json.dumps(schema, indent=4))
486
481
 
487
482
 
488
- def _print_engine_state(gwy: Gateway, **kwargs: Any) -> None:
483
+ async def _save_state(gwy: Gateway) -> None:
484
+ """Save the gateway state to files.
485
+
486
+ :param gwy: The gateway instance.
487
+ """
488
+ schema, msgs = await gwy.get_state()
489
+ await asyncio.to_thread(_write_state, schema, msgs)
490
+
491
+
492
+ async def _print_engine_state(gwy: Gateway, **kwargs: Any) -> None:
489
493
  """Print the current engine state (schema and packets).
490
494
 
491
495
  :param gwy: The gateway instance.
492
496
  :param kwargs: Command arguments to determine verbosity.
493
497
  """
494
- (schema, packets) = gwy.get_state(include_expired=True)
498
+ (schema, packets) = await gwy.get_state(include_expired=True)
495
499
 
496
500
  if kwargs["print_state"] > 0:
497
501
  print(f"schema: {json.dumps(schema, indent=4)}\r\n")
@@ -671,10 +675,10 @@ async def async_main(command: str, lib_kwargs: dict[str, Any], **kwargs: Any) ->
671
675
  print(f"\r\nclient.py: Engine stopped: {msg}")
672
676
 
673
677
  # if kwargs["save_state"]:
674
- # _save_state(gwy)
678
+ # await _save_state(gwy)
675
679
 
676
680
  if kwargs["print_state"]:
677
- _print_engine_state(gwy, **kwargs)
681
+ await _print_engine_state(gwy, **kwargs)
678
682
 
679
683
  elif command == EXECUTE:
680
684
  print_results(gwy, **kwargs)
@@ -35,7 +35,7 @@ from typing import TYPE_CHECKING, Any, NewType
35
35
 
36
36
  from ramses_tx import CODES_SCHEMA, RQ, Code, Message, Packet
37
37
 
38
- from .storage import StorageWorker
38
+ from .storage import PacketLogEntry, StorageWorker
39
39
 
40
40
  if TYPE_CHECKING:
41
41
  DtmStrT = NewType("DtmStrT", str)
@@ -241,28 +241,30 @@ class MessageIndex:
241
241
  :param dt_now: current timestamp
242
242
  :param _cutoff: the oldest timestamp to retain, default is 24 hours ago
243
243
  """
244
- msgs = None
245
244
  dtm = dt_now - _cutoff
246
245
 
247
- self._cu.execute("SELECT dtm FROM messages WHERE dtm >= ?", (dtm,))
248
- rows = self._cu.fetchall() # fetch dtm of current messages to retain
246
+ # Submit prune request to worker (Non-blocking I/O)
247
+ self._worker.submit_prune(dtm)
248
+
249
+ # Prune in-memory cache synchronously (Fast CPU-bound op)
250
+ dtm_iso = dtm.isoformat(timespec="microseconds")
249
251
 
250
252
  try: # make this operation atomic, i.e. update self._msgs only on success
251
253
  await self._lock.acquire()
252
- self._cu.execute("DELETE FROM messages WHERE dtm < ?", (dtm,))
253
- msgs = OrderedDict({row[0]: self._msgs[row[0]] for row in rows})
254
- self._cx.commit()
254
+ # Rebuild dict keeping only newer items
255
+ self._msgs = OrderedDict(
256
+ (k, v) for k, v in self._msgs.items() if k >= dtm_iso
257
+ )
255
258
 
256
- except sqlite3.Error: # need to tighten?
257
- self._cx.rollback()
259
+ except Exception as err:
260
+ _LOGGER.warning("MessageIndex housekeeping error: %s", err)
258
261
  else:
259
- self._msgs = msgs
262
+ _LOGGER.debug(
263
+ "MessageIndex housekeeping completed, retained messages >= %s",
264
+ dtm_iso,
265
+ )
260
266
  finally:
261
267
  self._lock.release()
262
- if msgs:
263
- _LOGGER.debug(
264
- "MessageIndex size was: %d, now: %d", len(rows), len(msgs)
265
- )
266
268
 
267
269
  while True:
268
270
  self._last_housekeeping = dt.now()
@@ -345,15 +347,15 @@ class MessageIndex:
345
347
  # Avoid blocking read; worker handles REPLACE on unique constraint collision
346
348
 
347
349
  # Prepare data tuple for worker
348
- data = (
349
- _now,
350
- verb,
351
- src,
352
- src,
353
- code,
354
- None,
355
- hdr,
356
- "|",
350
+ data = PacketLogEntry(
351
+ dtm=_now,
352
+ verb=verb,
353
+ src=src,
354
+ dst=src,
355
+ code=code,
356
+ ctx=None,
357
+ hdr=hdr,
358
+ plk="|",
357
359
  )
358
360
 
359
361
  self._worker.submit_packet(data)
@@ -390,15 +392,15 @@ class MessageIndex:
390
392
  # _old_msgs = self._delete_from(hdr=msg._pkt._hdr)
391
393
  # Refactor: Worker uses INSERT OR REPLACE to handle collision
392
394
 
393
- data = (
394
- msg.dtm,
395
- str(msg.verb),
396
- msg.src.id,
397
- msg.dst.id,
398
- str(msg.code),
399
- msg_pkt_ctx,
400
- msg._pkt._hdr,
401
- payload_keys(msg.payload),
395
+ data = PacketLogEntry(
396
+ dtm=msg.dtm,
397
+ verb=str(msg.verb),
398
+ src=msg.src.id,
399
+ dst=msg.dst.id,
400
+ code=str(msg.code),
401
+ ctx=msg_pkt_ctx,
402
+ hdr=msg._pkt._hdr,
403
+ plk=payload_keys(msg.payload),
402
404
  )
403
405
 
404
406
  self._worker.submit_packet(data)
@@ -913,7 +913,9 @@ class _Discovery(_MessageDB):
913
913
  sql, (self.id[:_ID_SLICE], self.id[:_ID_SLICE])
914
914
  ):
915
915
  _LOGGER.debug("Fetched OT ctx from index: %s", rec[0])
916
- res.append(rec[0])
916
+ # SQLite can return int, expected str (hex)
917
+ val = f"{rec[0]:02X}" if isinstance(rec[0], int) else rec[0]
918
+ res.append(val)
917
919
  else: # TODO(eb): remove next Q1 2026
918
920
  res_dict: dict[bool | str | None, Message] | list[Any] = self._msgz[
919
921
  Code._3220
@@ -12,6 +12,7 @@ from __future__ import annotations
12
12
  import asyncio
13
13
  import logging
14
14
  from collections.abc import Awaitable, Callable
15
+ from logging.handlers import QueueListener
15
16
  from types import SimpleNamespace
16
17
  from typing import TYPE_CHECKING, Any
17
18
 
@@ -101,6 +102,7 @@ class Gateway(Engine):
101
102
  known_list: DeviceListT | None = None,
102
103
  loop: asyncio.AbstractEventLoop | None = None,
103
104
  transport_constructor: Callable[..., Awaitable[RamsesTransportT]] | None = None,
105
+ hgi_id: str | None = None,
104
106
  **kwargs: Any,
105
107
  ) -> None:
106
108
  """Initialize the Gateway instance.
@@ -121,6 +123,8 @@ class Gateway(Engine):
121
123
  :type loop: asyncio.AbstractEventLoop | None, optional
122
124
  :param transport_constructor: A factory for creating the transport layer, defaults to None.
123
125
  :type transport_constructor: Callable[..., Awaitable[RamsesTransportT]] | None, optional
126
+ :param hgi_id: The Device ID to use for the HGI (gateway), overriding defaults.
127
+ :type hgi_id: str | None, optional
124
128
  :param kwargs: Additional configuration parameters passed to the engine and schema.
125
129
  :type kwargs: Any
126
130
  """
@@ -138,6 +142,7 @@ class Gateway(Engine):
138
142
  block_list=block_list,
139
143
  known_list=known_list,
140
144
  loop=loop,
145
+ hgi_id=hgi_id,
141
146
  transport_constructor=transport_constructor,
142
147
  **SCH_ENGINE_CONFIG(config),
143
148
  )
@@ -159,6 +164,7 @@ class Gateway(Engine):
159
164
  self.device_by_id: dict[DeviceIdT, Device] = {}
160
165
 
161
166
  self.msg_db: MessageIndex | None = None
167
+ self._pkt_log_listener: QueueListener | None = None
162
168
 
163
169
  def __repr__(self) -> str:
164
170
  """Return a string representation of the Gateway.
@@ -218,10 +224,12 @@ class Gateway(Engine):
218
224
  if system.dhw:
219
225
  system.dhw._start_discovery_poller()
220
226
 
221
- await set_pkt_logging_config( # type: ignore[arg-type]
227
+ _, self._pkt_log_listener = await set_pkt_logging_config( # type: ignore[arg-type]
222
228
  cc_console=self.config.reduce_processing >= DONT_CREATE_MESSAGES,
223
229
  **self._packet_log,
224
230
  )
231
+ if self._pkt_log_listener:
232
+ self._pkt_log_listener.start()
225
233
 
226
234
  # initialize SQLite index, set in _tx/Engine
227
235
  if self._sqlite_index: # TODO(eb): default to True in Q1 2026
@@ -267,12 +275,21 @@ class Gateway(Engine):
267
275
  :returns: None
268
276
  :rtype: None
269
277
  """
278
+ # Stop the Engine first to ensure no tasks/callbacks try to write
279
+ # to the DB while we are closing it.
280
+ await super().stop()
281
+
282
+ if self._pkt_log_listener:
283
+ self._pkt_log_listener.stop()
284
+ # Close handlers to ensure files are flushed/closed
285
+ for handler in self._pkt_log_listener.handlers:
286
+ handler.close()
287
+ self._pkt_log_listener = None
270
288
 
271
289
  if self.msg_db:
272
290
  self.msg_db.stop()
273
- await super().stop()
274
291
 
275
- def _pause(self, *args: Any) -> None:
292
+ async def _pause(self, *args: Any) -> None:
276
293
  """Pause the (unpaused) gateway (disables sending/discovery).
277
294
 
278
295
  There is the option to save other objects, as `args`.
@@ -288,12 +305,12 @@ class Gateway(Engine):
288
305
  self.config.disable_discovery, disc_flag = True, self.config.disable_discovery
289
306
 
290
307
  try:
291
- super()._pause(disc_flag, *args)
308
+ await super()._pause(disc_flag, *args)
292
309
  except RuntimeError:
293
310
  self.config.disable_discovery = disc_flag
294
311
  raise
295
312
 
296
- def _resume(self) -> tuple[Any]:
313
+ async def _resume(self) -> tuple[Any]:
297
314
  """Resume the (paused) gateway (enables sending/discovery, if applicable).
298
315
 
299
316
  Will restore other objects, as `args`.
@@ -305,11 +322,13 @@ class Gateway(Engine):
305
322
 
306
323
  _LOGGER.debug("Gateway: Resuming engine...")
307
324
 
308
- self.config.disable_discovery, *args = super()._resume() # type: ignore[assignment]
325
+ # args_tuple = await super()._resume()
326
+ # self.config.disable_discovery, *args = args_tuple # type: ignore[assignment]
327
+ self.config.disable_discovery, *args = await super()._resume() # type: ignore[assignment]
309
328
 
310
329
  return args
311
330
 
312
- def get_state(
331
+ async def get_state(
313
332
  self, include_expired: bool = False
314
333
  ) -> tuple[dict[str, Any], dict[str, str]]:
315
334
  """Return the current schema & state (may include expired packets).
@@ -320,7 +339,7 @@ class Gateway(Engine):
320
339
  :rtype: tuple[dict[str, Any], dict[str, str]]
321
340
  """
322
341
 
323
- self._pause()
342
+ await self._pause()
324
343
 
325
344
  def wanted_msg(msg: Message, include_expired: bool = False) -> bool:
326
345
  if msg.code == Code._313F:
@@ -357,7 +376,7 @@ class Gateway(Engine):
357
376
  }
358
377
  # _LOGGER.warning("Missing MessageIndex")
359
378
 
360
- self._resume()
379
+ await self._resume()
361
380
 
362
381
  return self.schema, dict(sorted(pkts.items()))
363
382
 
@@ -392,7 +411,7 @@ class Gateway(Engine):
392
411
  tmp_transport: RamsesTransportT # mypy hint
393
412
 
394
413
  _LOGGER.debug("Gateway: Restoring a cached packet log...")
395
- self._pause()
414
+ await self._pause()
396
415
 
397
416
  if _clear_state: # only intended for test suite use
398
417
  clear_state()
@@ -428,7 +447,7 @@ class Gateway(Engine):
428
447
  await tmp_transport.get_extra_info(SZ_READER_TASK)
429
448
 
430
449
  _LOGGER.debug("Gateway: Restored, resuming")
431
- self._resume()
450
+ await self._resume()
432
451
 
433
452
  def _add_device(self, dev: Device) -> None: # TODO: also: _add_system()
434
453
  """Add a device to the gateway (called by devices during instantiation).
@@ -7,24 +7,46 @@ import logging
7
7
  import queue
8
8
  import sqlite3
9
9
  import threading
10
- from typing import Any
10
+ from typing import Any, NamedTuple
11
11
 
12
12
  _LOGGER = logging.getLogger(__name__)
13
13
 
14
14
 
15
+ class PacketLogEntry(NamedTuple):
16
+ """Represents a packet to be written to the database."""
17
+
18
+ dtm: Any
19
+ verb: str
20
+ src: str
21
+ dst: str
22
+ code: str
23
+ ctx: str | None
24
+ hdr: str
25
+ plk: str
26
+
27
+
28
+ class PruneRequest(NamedTuple):
29
+ """Represents a request to prune old records."""
30
+
31
+ dtm_limit: Any
32
+
33
+
34
+ QueueItem = PacketLogEntry | PruneRequest | tuple[str, Any] | None
35
+
36
+
15
37
  class StorageWorker:
16
38
  """A background worker thread to handle blocking storage I/O asynchronously."""
17
39
 
18
- def __init__(self, db_path: str = ":memory:"):
40
+ def __init__(self, db_path: str = ":memory:") -> None:
19
41
  """Initialize the storage worker thread."""
20
42
  self._db_path = db_path
21
- self._queue: queue.SimpleQueue[tuple[str, Any] | None] = queue.SimpleQueue()
43
+ self._queue: queue.SimpleQueue[QueueItem] = queue.SimpleQueue()
22
44
  self._ready_event = threading.Event()
23
45
 
24
46
  self._thread = threading.Thread(
25
47
  target=self._run,
26
48
  name="RamsesStorage",
27
- daemon=True, # FIX: Set to True so the process can exit even if stop() is missed
49
+ daemon=True, # Allows process exit even if stop() is missed
28
50
  )
29
51
  self._thread.start()
30
52
 
@@ -32,16 +54,16 @@ class StorageWorker:
32
54
  """Wait until the database is initialized and ready."""
33
55
  return self._ready_event.wait(timeout)
34
56
 
35
- def submit_packet(self, packet_data: tuple[Any, ...]) -> None:
57
+ def submit_packet(self, packet: PacketLogEntry) -> None:
36
58
  """Submit a packet tuple for SQL insertion (Non-blocking)."""
37
- self._queue.put(("SQL", packet_data))
59
+ self._queue.put(packet)
60
+
61
+ def submit_prune(self, dtm_limit: Any) -> None:
62
+ """Submit a prune request for SQL deletion (Non-blocking)."""
63
+ self._queue.put(PruneRequest(dtm_limit))
38
64
 
39
65
  def flush(self, timeout: float = 10.0) -> None:
40
66
  """Block until all currently pending tasks are processed."""
41
- # REMOVED: if self._queue.empty(): return
42
- # This check caused a race condition where flush() returned before
43
- # the worker finished committing the last item it just popped.
44
-
45
67
  # We inject a special marker into the queue
46
68
  sentinel = threading.Event()
47
69
  self._queue.put(("MARKER", sentinel))
@@ -89,7 +111,7 @@ class StorageWorker:
89
111
  detect_types=sqlite3.PARSE_DECLTYPES | sqlite3.PARSE_COLNAMES,
90
112
  check_same_thread=False,
91
113
  uri=True,
92
- timeout=10.0, # Increased timeout for locking
114
+ timeout=10.0,
93
115
  )
94
116
 
95
117
  # Enable Write-Ahead Logging for concurrency
@@ -116,16 +138,9 @@ class StorageWorker:
116
138
  if item is None: # Shutdown signal
117
139
  break
118
140
 
119
- task_type, data = item
120
-
121
- if task_type == "MARKER":
122
- # Flush requested
123
- data.set()
124
- continue
125
-
126
- if task_type == "SQL":
141
+ if isinstance(item, PacketLogEntry):
127
142
  # Optimization: Batch processing
128
- batch = [data]
143
+ batch = [item]
129
144
  # Drain queue of pending SQL tasks to bulk insert
130
145
  while not self._queue.empty():
131
146
  try:
@@ -135,22 +150,19 @@ class StorageWorker:
135
150
  self._queue.put(None) # Re-queue poison pill
136
151
  break
137
152
 
138
- next_type, next_data = next_item
139
- if next_type == "SQL":
140
- batch.append(next_data)
141
- elif next_type == "MARKER":
142
- # Handle marker after this batch
143
- self._queue.put(next_item) # Re-queue marker
144
- break
153
+ if isinstance(next_item, PacketLogEntry):
154
+ batch.append(next_item)
145
155
  else:
146
- pass
156
+ # Handle other types after this batch
157
+ self._queue.put(next_item) # Re-queue
158
+ break
147
159
  except queue.Empty:
148
160
  break
149
161
 
150
162
  try:
151
163
  conn.executemany(
152
164
  """
153
- INSERT OR REPLACE INTO messages
165
+ INSERT OR REPLACE INTO messages
154
166
  (dtm, verb, src, dst, code, ctx, hdr, plk)
155
167
  VALUES (?, ?, ?, ?, ?, ?, ?, ?)
156
168
  """,
@@ -160,6 +172,20 @@ class StorageWorker:
160
172
  except sqlite3.Error as err:
161
173
  _LOGGER.error("SQL Write Failed: %s", err)
162
174
 
175
+ elif isinstance(item, PruneRequest):
176
+ try:
177
+ conn.execute(
178
+ "DELETE FROM messages WHERE dtm < ?", (item.dtm_limit,)
179
+ )
180
+ conn.commit()
181
+ _LOGGER.debug("Pruned records older than %s", item.dtm_limit)
182
+ except sqlite3.Error as err:
183
+ _LOGGER.error("SQL Prune Failed: %s", err)
184
+
185
+ elif isinstance(item, tuple) and item[0] == "MARKER":
186
+ # Flush requested
187
+ item[1].set()
188
+
163
189
  except Exception as err:
164
190
  _LOGGER.exception("StorageWorker encountered an error: %s", err)
165
191
 
@@ -137,7 +137,7 @@ class SystemBase(Parent, Entity): # 3B00 (multi-relay)
137
137
  self._child_id = FF # NOTE: domain_id
138
138
 
139
139
  self._app_cntrl: BdrSwitch | OtbGateway | None = None
140
- self._heat_demand = None
140
+ self._heat_demand: dict[str, Any] | None = None
141
141
 
142
142
  def __repr__(self) -> str:
143
143
  return f"{self.ctl.id} ({self._SLUG})"
@@ -217,17 +217,33 @@ class SystemBase(Parent, Entity): # 3B00 (multi-relay)
217
217
  super()._handle_msg(msg)
218
218
 
219
219
  if msg.code == Code._000C:
220
- if msg.payload[SZ_ZONE_TYPE] == DEV_ROLE_MAP.APP and msg.payload.get(
221
- SZ_DEVICES
222
- ):
223
- self._gwy.get_device(
224
- msg.payload[SZ_DEVICES][0], parent=self, child_id=FC
225
- ) # sets self._app_cntrl
220
+ if isinstance(msg.payload, dict):
221
+ if msg.payload[SZ_ZONE_TYPE] == DEV_ROLE_MAP.APP and msg.payload.get(
222
+ SZ_DEVICES
223
+ ):
224
+ self._gwy.get_device(
225
+ msg.payload[SZ_DEVICES][0], parent=self, child_id=FC
226
+ ) # sets self._app_cntrl
227
+ else:
228
+ _LOGGER.warning(
229
+ f"{msg!r} < Unexpected payload type for {msg.code}: {type(msg.payload)} (expected dict)"
230
+ )
226
231
  return
227
232
 
228
- if msg.code == Code._3150:
229
- if msg.payload.get(SZ_DOMAIN_ID) == FC and msg.verb in (I_, RP):
230
- self._heat_demand = msg.payload
233
+ if msg.code == Code._3150 and msg.verb in (I_, RP):
234
+ # 3150 payload can be a dict (old) or list (new, multi-zone)
235
+ if isinstance(msg.payload, list):
236
+ if payload := next(
237
+ (d for d in msg.payload if d.get(SZ_DOMAIN_ID) == FC), None
238
+ ):
239
+ self._heat_demand = payload
240
+ elif isinstance(msg.payload, dict):
241
+ if msg.payload.get(SZ_DOMAIN_ID) == FC:
242
+ self._heat_demand = msg.payload
243
+ else:
244
+ _LOGGER.warning(
245
+ f"{msg!r} < Unexpected payload type for {msg.code}: {type(msg.payload)} (expected list/dict)"
246
+ )
231
247
 
232
248
  if self._gwy.config.enable_eavesdrop and not self.appliance_control:
233
249
  eavesdrop_appliance_control(msg)
@@ -588,7 +604,12 @@ class ScheduleSync(SystemBase): # 0006 (+/- 0404?)
588
604
  super()._handle_msg(msg)
589
605
 
590
606
  if msg.code == Code._0006:
591
- self._msg_0006 = msg
607
+ if isinstance(msg.payload, dict):
608
+ self._msg_0006 = msg
609
+ else:
610
+ _LOGGER.warning(
611
+ f"{msg!r} < Unexpected payload type for {msg.code}: {type(msg.payload)} (expected dict)"
612
+ )
592
613
 
593
614
  async def _schedule_version(self, *, force_io: bool = False) -> tuple[int, bool]:
594
615
  """Return the global schedule version number, and an indication if I/O was done.
@@ -706,7 +727,12 @@ class Logbook(SystemBase): # 0418
706
727
  super()._handle_msg(msg)
707
728
 
708
729
  if msg.code == Code._0418: # and msg.verb in (I_, RP):
709
- self._faultlog.handle_msg(msg)
730
+ if isinstance(msg.payload, dict):
731
+ self._faultlog.handle_msg(msg)
732
+ else:
733
+ _LOGGER.warning(
734
+ f"{msg!r} < Unexpected payload type for {msg.code}: {type(msg.payload)} (expected dict)"
735
+ )
710
736
 
711
737
  async def get_faultlog(
712
738
  self,
@@ -1,4 +1,4 @@
1
1
  """RAMSES RF - a RAMSES-II protocol decoder & analyser (application layer)."""
2
2
 
3
- __version__ = "0.53.3"
3
+ __version__ = "0.53.5"
4
4
  VERSION = __version__
@@ -7,6 +7,7 @@ from __future__ import annotations
7
7
 
8
8
  import asyncio
9
9
  from functools import partial
10
+ from logging.handlers import QueueListener
10
11
  from typing import TYPE_CHECKING, Any
11
12
 
12
13
  from .address import (
@@ -156,17 +157,19 @@ if TYPE_CHECKING:
156
157
  from logging import Logger
157
158
 
158
159
 
159
- async def set_pkt_logging_config(**config: Any) -> Logger:
160
+ async def set_pkt_logging_config(**config: Any) -> tuple[Logger, QueueListener | None]:
160
161
  """
161
162
  Set up ramses packet logging to a file or port.
162
- Must run async in executor to prevent HA blocking call opening packet log file (issue #200)
163
+ Must run async in executor to prevent HA blocking call opening packet log file.
163
164
 
164
165
  :param config: if file_name is included, opens packet_log file
165
- :return: a logging.Logger
166
+ :return: a tuple (logging.Logger, QueueListener)
166
167
  """
167
168
  loop = asyncio.get_running_loop()
168
- await loop.run_in_executor(None, partial(set_pkt_logging, PKT_LOGGER, **config))
169
- return PKT_LOGGER
169
+ listener = await loop.run_in_executor(
170
+ None, partial(set_pkt_logging, PKT_LOGGER, **config)
171
+ )
172
+ return PKT_LOGGER, listener
170
173
 
171
174
 
172
175
  def extract_known_hgi_id(
@@ -20,10 +20,12 @@ DEFAULT_DISABLE_QOS: Final[bool | None] = None
20
20
  DEFAULT_WAIT_FOR_REPLY: Final[bool | None] = None
21
21
 
22
22
  #: Waiting for echo pkt after cmd sent (seconds)
23
- DEFAULT_ECHO_TIMEOUT: Final[float] = 0.50
23
+ # NOTE: Increased to 3.0s to support high-latency transports (e.g., MQTT)
24
+ DEFAULT_ECHO_TIMEOUT: Final[float] = 3.00
24
25
 
25
26
  #: Waiting for reply pkt after echo pkt rcvd (seconds)
26
- DEFAULT_RPLY_TIMEOUT: Final[float] = 0.50
27
+ # NOTE: Increased to 3.0s to support high-latency transports (e.g., MQTT)
28
+ DEFAULT_RPLY_TIMEOUT: Final[float] = 3.00
27
29
  DEFAULT_BUFFER_SIZE: Final[int] = 32
28
30
 
29
31
  #: Total waiting for successful send (seconds)