ramses-rf 0.53.2__tar.gz → 0.53.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.
- {ramses_rf-0.53.2 → ramses_rf-0.53.3}/PKG-INFO +1 -1
- {ramses_rf-0.53.2 → ramses_rf-0.53.3}/ramses_rf/database.py +113 -61
- ramses_rf-0.53.3/ramses_rf/storage.py +168 -0
- {ramses_rf-0.53.2 → ramses_rf-0.53.3}/ramses_rf/version.py +1 -1
- {ramses_rf-0.53.2 → ramses_rf-0.53.3}/ramses_tx/parsers.py +3 -1
- {ramses_rf-0.53.2 → ramses_rf-0.53.3}/ramses_tx/ramses.py +1 -1
- {ramses_rf-0.53.2 → ramses_rf-0.53.3}/ramses_tx/transport.py +26 -26
- {ramses_rf-0.53.2 → ramses_rf-0.53.3}/ramses_tx/version.py +1 -1
- ramses_rf-0.53.3/requirements/requirements_docs.txt +15 -0
- {ramses_rf-0.53.2 → ramses_rf-0.53.3}/tests/tests/parsers/code_31da.log +7 -0
- ramses_rf-0.53.3/tests/tests/test_storage.py +115 -0
- {ramses_rf-0.53.2 → ramses_rf-0.53.3}/tests/tests_rf/test_database.py +5 -4
- ramses_rf-0.53.2/requirements/requirements_docs.txt +0 -17
- {ramses_rf-0.53.2 → ramses_rf-0.53.3}/.github/ISSUE_TEMPLATE/bug_report.md +0 -0
- {ramses_rf-0.53.2 → ramses_rf-0.53.3}/.github/dependabot.yml +0 -0
- {ramses_rf-0.53.2 → ramses_rf-0.53.3}/.github/workflows/check-cov.yml +0 -0
- {ramses_rf-0.53.2 → ramses_rf-0.53.3}/.github/workflows/check-lint.yml +0 -0
- {ramses_rf-0.53.2 → ramses_rf-0.53.3}/.github/workflows/check-test.yml +0 -0
- {ramses_rf-0.53.2 → ramses_rf-0.53.3}/.github/workflows/check-type.yml +0 -0
- {ramses_rf-0.53.2 → ramses_rf-0.53.3}/.github/workflows/publish-hatch.yml +0 -0
- {ramses_rf-0.53.2 → ramses_rf-0.53.3}/.gitignore +0 -0
- {ramses_rf-0.53.2 → ramses_rf-0.53.3}/.pre-commit-config.yaml +0 -0
- {ramses_rf-0.53.2 → ramses_rf-0.53.3}/LICENSE +0 -0
- {ramses_rf-0.53.2 → ramses_rf-0.53.3}/README-developers.md +0 -0
- {ramses_rf-0.53.2 → ramses_rf-0.53.3}/README.md +0 -0
- {ramses_rf-0.53.2 → ramses_rf-0.53.3}/client.py +0 -0
- {ramses_rf-0.53.2 → ramses_rf-0.53.3}/docs/Makefile +0 -0
- {ramses_rf-0.53.2 → ramses_rf-0.53.3}/docs/make.bat +0 -0
- {ramses_rf-0.53.2 → ramses_rf-0.53.3}/docs/source/_static/CC-BY-NC-SA-4.0.txt +0 -0
- {ramses_rf-0.53.2 → ramses_rf-0.53.3}/docs/source/_static/ramses_rf_logo.png +0 -0
- {ramses_rf-0.53.2 → ramses_rf-0.53.3}/docs/source/binding_process.md +0 -0
- {ramses_rf-0.53.2 → ramses_rf-0.53.3}/docs/source/conf.py +0 -0
- {ramses_rf-0.53.2 → ramses_rf-0.53.3}/docs/source/glossary.rst +0 -0
- {ramses_rf-0.53.2 → ramses_rf-0.53.3}/docs/source/index.rst +0 -0
- {ramses_rf-0.53.2 → ramses_rf-0.53.3}/docs/source/modules.rst +0 -0
- {ramses_rf-0.53.2 → ramses_rf-0.53.3}/docs/source/ramses_cli.rst +0 -0
- {ramses_rf-0.53.2 → ramses_rf-0.53.3}/docs/source/ramses_rf.device.rst +0 -0
- {ramses_rf-0.53.2 → ramses_rf-0.53.3}/docs/source/ramses_rf.rst +0 -0
- {ramses_rf-0.53.2 → ramses_rf-0.53.3}/docs/source/ramses_rf.system.rst +0 -0
- {ramses_rf-0.53.2 → ramses_rf-0.53.3}/docs/source/ramses_tx.rst +0 -0
- {ramses_rf-0.53.2 → ramses_rf-0.53.3}/docs/source/usage.md +0 -0
- {ramses_rf-0.53.2 → ramses_rf-0.53.3}/misc/2411_parser.py +0 -0
- {ramses_rf-0.53.2 → ramses_rf-0.53.3}/misc/fingerprints.log +0 -0
- {ramses_rf-0.53.2 → ramses_rf-0.53.3}/misc/ser2net.yaml +0 -0
- {ramses_rf-0.53.2 → ramses_rf-0.53.3}/misc/ti_3410/notes.sh +0 -0
- {ramses_rf-0.53.2 → ramses_rf-0.53.3}/misc/ti_3410/ti_3410.fw +0 -0
- {ramses_rf-0.53.2 → ramses_rf-0.53.3}/pyproject.toml +0 -0
- {ramses_rf-0.53.2 → ramses_rf-0.53.3}/ramses_cli/__init__.py +0 -0
- {ramses_rf-0.53.2 → ramses_rf-0.53.3}/ramses_cli/client.py +0 -0
- {ramses_rf-0.53.2 → ramses_rf-0.53.3}/ramses_cli/debug.py +0 -0
- {ramses_rf-0.53.2 → ramses_rf-0.53.3}/ramses_cli/discovery.py +0 -0
- {ramses_rf-0.53.2 → ramses_rf-0.53.3}/ramses_cli/py.typed +0 -0
- {ramses_rf-0.53.2 → ramses_rf-0.53.3}/ramses_cli/utils/cat_slow.py +0 -0
- {ramses_rf-0.53.2 → ramses_rf-0.53.3}/ramses_cli/utils/convert.py +0 -0
- {ramses_rf-0.53.2 → ramses_rf-0.53.3}/ramses_rf/__init__.py +0 -0
- {ramses_rf-0.53.2 → ramses_rf-0.53.3}/ramses_rf/binding_fsm.py +0 -0
- {ramses_rf-0.53.2 → ramses_rf-0.53.3}/ramses_rf/const.py +0 -0
- {ramses_rf-0.53.2 → ramses_rf-0.53.3}/ramses_rf/device/__init__.py +0 -0
- {ramses_rf-0.53.2 → ramses_rf-0.53.3}/ramses_rf/device/base.py +0 -0
- {ramses_rf-0.53.2 → ramses_rf-0.53.3}/ramses_rf/device/heat.py +0 -0
- {ramses_rf-0.53.2 → ramses_rf-0.53.3}/ramses_rf/device/hvac.py +0 -0
- {ramses_rf-0.53.2 → ramses_rf-0.53.3}/ramses_rf/dispatcher.py +0 -0
- {ramses_rf-0.53.2 → ramses_rf-0.53.3}/ramses_rf/entity_base.py +0 -0
- {ramses_rf-0.53.2 → ramses_rf-0.53.3}/ramses_rf/exceptions.py +0 -0
- {ramses_rf-0.53.2 → ramses_rf-0.53.3}/ramses_rf/gateway.py +0 -0
- {ramses_rf-0.53.2 → ramses_rf-0.53.3}/ramses_rf/helpers.py +0 -0
- {ramses_rf-0.53.2 → ramses_rf-0.53.3}/ramses_rf/py.typed +0 -0
- {ramses_rf-0.53.2 → ramses_rf-0.53.3}/ramses_rf/schemas.py +0 -0
- {ramses_rf-0.53.2 → ramses_rf-0.53.3}/ramses_rf/system/__init__.py +0 -0
- {ramses_rf-0.53.2 → ramses_rf-0.53.3}/ramses_rf/system/faultlog.py +0 -0
- {ramses_rf-0.53.2 → ramses_rf-0.53.3}/ramses_rf/system/heat.py +0 -0
- {ramses_rf-0.53.2 → ramses_rf-0.53.3}/ramses_rf/system/schedule.py +0 -0
- {ramses_rf-0.53.2 → ramses_rf-0.53.3}/ramses_rf/system/zones.py +0 -0
- {ramses_rf-0.53.2 → ramses_rf-0.53.3}/ramses_tx/__init__.py +0 -0
- {ramses_rf-0.53.2 → ramses_rf-0.53.3}/ramses_tx/address.py +0 -0
- {ramses_rf-0.53.2 → ramses_rf-0.53.3}/ramses_tx/command.py +0 -0
- {ramses_rf-0.53.2 → ramses_rf-0.53.3}/ramses_tx/const.py +0 -0
- {ramses_rf-0.53.2 → ramses_rf-0.53.3}/ramses_tx/exceptions.py +0 -0
- {ramses_rf-0.53.2 → ramses_rf-0.53.3}/ramses_tx/fingerprints.py +0 -0
- {ramses_rf-0.53.2 → ramses_rf-0.53.3}/ramses_tx/frame.py +0 -0
- {ramses_rf-0.53.2 → ramses_rf-0.53.3}/ramses_tx/gateway.py +0 -0
- {ramses_rf-0.53.2 → ramses_rf-0.53.3}/ramses_tx/helpers.py +0 -0
- {ramses_rf-0.53.2 → ramses_rf-0.53.3}/ramses_tx/logger.py +0 -0
- {ramses_rf-0.53.2 → ramses_rf-0.53.3}/ramses_tx/message.py +0 -0
- {ramses_rf-0.53.2 → ramses_rf-0.53.3}/ramses_tx/opentherm.py +0 -0
- {ramses_rf-0.53.2 → ramses_rf-0.53.3}/ramses_tx/packet.py +0 -0
- {ramses_rf-0.53.2 → ramses_rf-0.53.3}/ramses_tx/protocol.py +0 -0
- {ramses_rf-0.53.2 → ramses_rf-0.53.3}/ramses_tx/protocol_fsm.py +0 -0
- {ramses_rf-0.53.2 → ramses_rf-0.53.3}/ramses_tx/py.typed +0 -0
- {ramses_rf-0.53.2 → ramses_rf-0.53.3}/ramses_tx/schemas.py +0 -0
- {ramses_rf-0.53.2 → ramses_rf-0.53.3}/ramses_tx/typed_dicts.py +0 -0
- {ramses_rf-0.53.2 → ramses_rf-0.53.3}/ramses_tx/typing.py +0 -0
- {ramses_rf-0.53.2 → ramses_rf-0.53.3}/requirements/requirements.txt +0 -0
- {ramses_rf-0.53.2 → ramses_rf-0.53.3}/requirements/requirements_dev.txt +0 -0
- {ramses_rf-0.53.2 → ramses_rf-0.53.3}/tests/deprecated/_test_apis_mock.py +0 -0
- {ramses_rf-0.53.2 → ramses_rf-0.53.3}/tests/deprecated/_test_mock_faultlog.py +0 -0
- {ramses_rf-0.53.2 → ramses_rf-0.53.3}/tests/deprecated/_test_mock_schedule.py +0 -0
- {ramses_rf-0.53.2 → ramses_rf-0.53.3}/tests/deprecated/_test_packets_bad.py +0 -0
- {ramses_rf-0.53.2 → ramses_rf-0.53.3}/tests/deprecated/_test_performance_WIP.py +0 -0
- {ramses_rf-0.53.2 → ramses_rf-0.53.3}/tests/deprecated/_test_state_mgt.py +0 -0
- {ramses_rf-0.53.2 → ramses_rf-0.53.3}/tests/deprecated/common.py +0 -0
- {ramses_rf-0.53.2 → ramses_rf-0.53.3}/tests/deprecated/mocked_devices/__init__.py +0 -0
- {ramses_rf-0.53.2 → ramses_rf-0.53.3}/tests/deprecated/mocked_devices/command.py +0 -0
- {ramses_rf-0.53.2 → ramses_rf-0.53.3}/tests/deprecated/mocked_devices/const.py +0 -0
- {ramses_rf-0.53.2 → ramses_rf-0.53.3}/tests/deprecated/mocked_devices/device_heat.py +0 -0
- {ramses_rf-0.53.2 → ramses_rf-0.53.3}/tests/deprecated/mocked_devices/device_hvac.py +0 -0
- {ramses_rf-0.53.2 → ramses_rf-0.53.3}/tests/deprecated/mocked_devices/transport.py +0 -0
- {ramses_rf-0.53.2 → ramses_rf-0.53.3}/tests/test_HA_MQTT/test_transport_callback.py +0 -0
- {ramses_rf-0.53.2 → ramses_rf-0.53.3}/tests/tests/__init__.py +0 -0
- {ramses_rf-0.53.2 → ramses_rf-0.53.3}/tests/tests/bindings/heat/ctl_bdr_91t.log +0 -0
- {ramses_rf-0.53.2 → ramses_rf-0.53.3}/tests/tests/bindings/heat/dts_ctl_sensor.log +0 -0
- {ramses_rf-0.53.2 → ramses_rf-0.53.3}/tests/tests/bindings/heat/hcw_ctl_sensor.log +0 -0
- {ramses_rf-0.53.2 → ramses_rf-0.53.3}/tests/tests/bindings/heat/rnd_ctl_sensor.log +0 -0
- {ramses_rf-0.53.2 → ramses_rf-0.53.3}/tests/tests/bindings/heat/rnd_ctl_sensor.yaml +0 -0
- {ramses_rf-0.53.2 → ramses_rf-0.53.3}/tests/tests/bindings/heat/trv_ctl.log +0 -0
- {ramses_rf-0.53.2 → ramses_rf-0.53.3}/tests/tests/bindings/hvac/co2_fan_itho.json +0 -0
- {ramses_rf-0.53.2 → ramses_rf-0.53.3}/tests/tests/bindings/hvac/co2_fan_itho.log +0 -0
- {ramses_rf-0.53.2 → ramses_rf-0.53.3}/tests/tests/bindings/hvac/co2_fan_itho.yaml +0 -0
- {ramses_rf-0.53.2 → ramses_rf-0.53.3}/tests/tests/bindings/hvac/dis_fan_orcon.json +0 -0
- {ramses_rf-0.53.2 → ramses_rf-0.53.3}/tests/tests/bindings/hvac/dis_fan_orcon.log +0 -0
- {ramses_rf-0.53.2 → ramses_rf-0.53.3}/tests/tests/bindings/hvac/rem_fan_climarad.log +0 -0
- {ramses_rf-0.53.2 → ramses_rf-0.53.3}/tests/tests/bindings/hvac/rem_fan_nuaire.json +0 -0
- {ramses_rf-0.53.2 → ramses_rf-0.53.3}/tests/tests/bindings/hvac/rem_fan_nuaire.log +0 -0
- {ramses_rf-0.53.2 → ramses_rf-0.53.3}/tests/tests/bindings/hvac/rem_fan_nuaire.yaml +0 -0
- {ramses_rf-0.53.2 → ramses_rf-0.53.3}/tests/tests/bindings/hvac/rem_fan_vasco.log +0 -0
- {ramses_rf-0.53.2 → ramses_rf-0.53.3}/tests/tests/bindings/hvac/rem_fan_ventura.log +0 -0
- {ramses_rf-0.53.2 → ramses_rf-0.53.3}/tests/tests/devices/device_02.log +0 -0
- {ramses_rf-0.53.2 → ramses_rf-0.53.3}/tests/tests/devices/device_04.log +0 -0
- {ramses_rf-0.53.2 → ramses_rf-0.53.3}/tests/tests/devices/device_10.log +0 -0
- {ramses_rf-0.53.2 → ramses_rf-0.53.3}/tests/tests/devices/device_13.log +0 -0
- {ramses_rf-0.53.2 → ramses_rf-0.53.3}/tests/tests/devices/device_22.log +0 -0
- {ramses_rf-0.53.2 → ramses_rf-0.53.3}/tests/tests/eavesdrop_dev_class/hvac/known_list_eavesdrop_off.json +0 -0
- {ramses_rf-0.53.2 → ramses_rf-0.53.3}/tests/tests/eavesdrop_dev_class/hvac/known_list_eavesdrop_on.json +0 -0
- {ramses_rf-0.53.2 → ramses_rf-0.53.3}/tests/tests/eavesdrop_dev_class/hvac/packet.log +0 -0
- {ramses_rf-0.53.2 → ramses_rf-0.53.3}/tests/tests/eavesdrop_schema/_trv_actuator_long/packet.log +0 -0
- {ramses_rf-0.53.2 → ramses_rf-0.53.3}/tests/tests/eavesdrop_schema/_trv_actuator_long/schema_eavesdrop_off.json +0 -0
- {ramses_rf-0.53.2 → ramses_rf-0.53.3}/tests/tests/eavesdrop_schema/_trv_actuator_long/schema_eavesdrop_on.json +0 -0
- {ramses_rf-0.53.2 → ramses_rf-0.53.3}/tests/tests/eavesdrop_schema/_trv_actuator_mixed/packet.log +0 -0
- {ramses_rf-0.53.2 → ramses_rf-0.53.3}/tests/tests/eavesdrop_schema/_trv_actuator_mixed/schema_eavesdrop_off.json +0 -0
- {ramses_rf-0.53.2 → ramses_rf-0.53.3}/tests/tests/eavesdrop_schema/_trv_actuator_mixed/schema_eavesdrop_on.json +0 -0
- {ramses_rf-0.53.2 → ramses_rf-0.53.3}/tests/tests/eavesdrop_schema/_ufh_circuits/packet.log +0 -0
- {ramses_rf-0.53.2 → ramses_rf-0.53.3}/tests/tests/eavesdrop_schema/_ufh_circuits/schema_eavesdrop_off.json +0 -0
- {ramses_rf-0.53.2 → ramses_rf-0.53.3}/tests/tests/eavesdrop_schema/_ufh_circuits/schema_eavesdrop_on.json +0 -0
- {ramses_rf-0.53.2 → ramses_rf-0.53.3}/tests/tests/eavesdrop_schema/app_cntrl/packet.log +0 -0
- {ramses_rf-0.53.2 → ramses_rf-0.53.3}/tests/tests/eavesdrop_schema/app_cntrl/schema_eavesdrop_off.json +0 -0
- {ramses_rf-0.53.2 → ramses_rf-0.53.3}/tests/tests/eavesdrop_schema/app_cntrl/schema_eavesdrop_on.json +0 -0
- {ramses_rf-0.53.2 → ramses_rf-0.53.3}/tests/tests/eavesdrop_schema/trv_actuators/packet.log +0 -0
- {ramses_rf-0.53.2 → ramses_rf-0.53.3}/tests/tests/eavesdrop_schema/trv_actuators/schema_eavesdrop_off.json +0 -0
- {ramses_rf-0.53.2 → ramses_rf-0.53.3}/tests/tests/eavesdrop_schema/trv_actuators/schema_eavesdrop_on.json +0 -0
- {ramses_rf-0.53.2 → ramses_rf-0.53.3}/tests/tests/eavesdrop_schema/zone_sensors_000/packet.log +0 -0
- {ramses_rf-0.53.2 → ramses_rf-0.53.3}/tests/tests/eavesdrop_schema/zone_sensors_000/schema_eavesdrop_off.json +0 -0
- {ramses_rf-0.53.2 → ramses_rf-0.53.3}/tests/tests/eavesdrop_schema/zone_sensors_000/schema_eavesdrop_on.json +0 -0
- {ramses_rf-0.53.2 → ramses_rf-0.53.3}/tests/tests/eavesdrop_schema/zone_sensors_001/packet.log +0 -0
- {ramses_rf-0.53.2 → ramses_rf-0.53.3}/tests/tests/eavesdrop_schema/zone_sensors_001/schema_eavesdrop_off.json +0 -0
- {ramses_rf-0.53.2 → ramses_rf-0.53.3}/tests/tests/eavesdrop_schema/zone_sensors_001/schema_eavesdrop_on.json +0 -0
- {ramses_rf-0.53.2 → ramses_rf-0.53.3}/tests/tests/eavesdrop_schema/zone_sensors_002/packet.log +0 -0
- {ramses_rf-0.53.2 → ramses_rf-0.53.3}/tests/tests/eavesdrop_schema/zone_sensors_002/schema_eavesdrop_off.json +0 -0
- {ramses_rf-0.53.2 → ramses_rf-0.53.3}/tests/tests/eavesdrop_schema/zone_sensors_002/schema_eavesdrop_on.json +0 -0
- {ramses_rf-0.53.2 → ramses_rf-0.53.3}/tests/tests/eavesdrop_schema/zone_sensors_003/packet.log +0 -0
- {ramses_rf-0.53.2 → ramses_rf-0.53.3}/tests/tests/eavesdrop_schema/zone_sensors_003/schema_eavesdrop_off.json +0 -0
- {ramses_rf-0.53.2 → ramses_rf-0.53.3}/tests/tests/eavesdrop_schema/zone_sensors_003/schema_eavesdrop_on.json +0 -0
- {ramses_rf-0.53.2 → ramses_rf-0.53.3}/tests/tests/eavesdrop_schema/zone_sensors_004/packet.log +0 -0
- {ramses_rf-0.53.2 → ramses_rf-0.53.3}/tests/tests/eavesdrop_schema/zone_sensors_004/schema_eavesdrop_off.json +0 -0
- {ramses_rf-0.53.2 → ramses_rf-0.53.3}/tests/tests/eavesdrop_schema/zone_sensors_004/schema_eavesdrop_on.json +0 -0
- {ramses_rf-0.53.2 → ramses_rf-0.53.3}/tests/tests/fingerprints/10e0_xxxx.log +0 -0
- {ramses_rf-0.53.2 → ramses_rf-0.53.3}/tests/tests/fingerprints/_gather.sh +0 -0
- {ramses_rf-0.53.2 → ramses_rf-0.53.3}/tests/tests/fingerprints/heat/01_EvoTouch_Colour.log +0 -0
- {ramses_rf-0.53.2 → ramses_rf-0.53.3}/tests/tests/fingerprints/heat/01_Evo_Color.log +0 -0
- {ramses_rf-0.53.2 → ramses_rf-0.53.3}/tests/tests/fingerprints/heat/01_IONA_RAI_Prototype.log +0 -0
- {ramses_rf-0.53.2 → ramses_rf-0.53.3}/tests/tests/fingerprints/heat/02_HCE80_V3.10_061117..log +0 -0
- {ramses_rf-0.53.2 → ramses_rf-0.53.3}/tests/tests/fingerprints/heat/04_HR92 Radiator Ctrl_.log +0 -0
- {ramses_rf-0.53.2 → ramses_rf-0.53.3}/tests/tests/fingerprints/heat/08_Jasper_EIM.log +0 -0
- {ramses_rf-0.53.2 → ramses_rf-0.53.3}/tests/tests/fingerprints/heat/10_R8810A_Bridge.log +0 -0
- {ramses_rf-0.53.2 → ramses_rf-0.53.3}/tests/tests/fingerprints/heat/10_R8820.log +0 -0
- {ramses_rf-0.53.2 → ramses_rf-0.53.3}/tests/tests/fingerprints/heat/30_Internet_Gateway.log +0 -0
- {ramses_rf-0.53.2 → ramses_rf-0.53.3}/tests/tests/fingerprints/heat/31_Jasper_Stat_TXXX.log +0 -0
- {ramses_rf-0.53.2 → ramses_rf-0.53.3}/tests/tests/fingerprints/heat/34_T87RF2025.log +0 -0
- {ramses_rf-0.53.2 → ramses_rf-0.53.3}/tests/tests/fingerprints/hvac/18_BRDG-02A55.log +0 -0
- {ramses_rf-0.53.2 → ramses_rf-0.53.3}/tests/tests/fingerprints/hvac/18_HRA82.log +0 -0
- {ramses_rf-0.53.2 → ramses_rf-0.53.3}/tests/tests/fingerprints/hvac/20.log +0 -0
- {ramses_rf-0.53.2 → ramses_rf-0.53.3}/tests/tests/fingerprints/hvac/21_CCU-12T20.log +0 -0
- {ramses_rf-0.53.2 → ramses_rf-0.53.3}/tests/tests/fingerprints/hvac/29_VMC-07RP01.log +0 -0
- {ramses_rf-0.53.2 → ramses_rf-0.53.3}/tests/tests/fingerprints/hvac/29_VMC-15RP01.log +0 -0
- {ramses_rf-0.53.2 → ramses_rf-0.53.3}/tests/tests/fingerprints/hvac/29_VMC-17RP01.log +0 -0
- {ramses_rf-0.53.2 → ramses_rf-0.53.3}/tests/tests/fingerprints/hvac/29_VMN-07LM01.log +0 -0
- {ramses_rf-0.53.2 → ramses_rf-0.53.3}/tests/tests/fingerprints/hvac/29_VMN-15LF01.log +0 -0
- {ramses_rf-0.53.2 → ramses_rf-0.53.3}/tests/tests/fingerprints/hvac/29_VMN-17LMP01.log +0 -0
- {ramses_rf-0.53.2 → ramses_rf-0.53.3}/tests/tests/fingerprints/hvac/29_VMS-15C16.log +0 -0
- {ramses_rf-0.53.2 → ramses_rf-0.53.3}/tests/tests/fingerprints/hvac/29_VMS-17HB01.log +0 -0
- {ramses_rf-0.53.2 → ramses_rf-0.53.3}/tests/tests/fingerprints/hvac/30_BRDG-02EM23.log +0 -0
- {ramses_rf-0.53.2 → ramses_rf-0.53.3}/tests/tests/fingerprints/hvac/30_BRDG-02JAS01.log +0 -0
- {ramses_rf-0.53.2 → ramses_rf-0.53.3}/tests/tests/fingerprints/hvac/32_VMC-15RPS34.log +0 -0
- {ramses_rf-0.53.2 → ramses_rf-0.53.3}/tests/tests/fingerprints/hvac/32_VMD-15RMS64.log +0 -0
- {ramses_rf-0.53.2 → ramses_rf-0.53.3}/tests/tests/fingerprints/hvac/32_VMD-15RMS86.log +0 -0
- {ramses_rf-0.53.2 → ramses_rf-0.53.3}/tests/tests/fingerprints/hvac/32_VMD-17RPS01.log +0 -0
- {ramses_rf-0.53.2 → ramses_rf-0.53.3}/tests/tests/fingerprints/hvac/32_VMN-23LM33.log +0 -0
- {ramses_rf-0.53.2 → ramses_rf-0.53.3}/tests/tests/fingerprints/hvac/32_VMN-23LMH23.log +0 -0
- {ramses_rf-0.53.2 → ramses_rf-0.53.3}/tests/tests/fingerprints/hvac/32_VMS-15CM17.log +0 -0
- {ramses_rf-0.53.2 → ramses_rf-0.53.3}/tests/tests/fingerprints/hvac/32_VMS-23C33.log +0 -0
- {ramses_rf-0.53.2 → ramses_rf-0.53.3}/tests/tests/fingerprints/hvac/32_VMS-23HB33.log +0 -0
- {ramses_rf-0.53.2 → ramses_rf-0.53.3}/tests/tests/fingerprints/hvac/32_VMZ-15V13.log +0 -0
- {ramses_rf-0.53.2 → ramses_rf-0.53.3}/tests/tests/fingerprints/hvac/37_VMD-07RPS13.log +0 -0
- {ramses_rf-0.53.2 → ramses_rf-0.53.3}/tests/tests/fingerprints/hvac/37_VMI-15MC01log +0 -0
- {ramses_rf-0.53.2 → ramses_rf-0.53.3}/tests/tests/fingerprints/hvac/37_VMI-15WSJ53.log +0 -0
- {ramses_rf-0.53.2 → ramses_rf-0.53.3}/tests/tests/fingerprints/hvac/37_VMS-02J52.log +0 -0
- {ramses_rf-0.53.2 → ramses_rf-0.53.3}/tests/tests/fingerprints/hvac/37_VMS-12C39.log +0 -0
- {ramses_rf-0.53.2 → ramses_rf-0.53.3}/tests/tests/fingerprints/hvac/99_CVE-RF.log +0 -0
- {ramses_rf-0.53.2 → ramses_rf-0.53.3}/tests/tests/fingerprints/hvac/99_VMS-17C01.log +0 -0
- {ramses_rf-0.53.2 → ramses_rf-0.53.3}/tests/tests/helpers.py +0 -0
- {ramses_rf-0.53.2 → ramses_rf-0.53.3}/tests/tests/logger/packet_in.log +0 -0
- {ramses_rf-0.53.2 → ramses_rf-0.53.3}/tests/tests/logger/packet_out.log +0 -0
- {ramses_rf-0.53.2 → ramses_rf-0.53.3}/tests/tests/logs/pkts_bad_000.log +0 -0
- {ramses_rf-0.53.2 → ramses_rf-0.53.3}/tests/tests/logs/pkts_tba_000.log +0 -0
- {ramses_rf-0.53.2 → ramses_rf-0.53.3}/tests/tests/logs/system_cache.json +0 -0
- {ramses_rf-0.53.2 → ramses_rf-0.53.3}/tests/tests/parser_helpers/pkt_addr_set.log +0 -0
- {ramses_rf-0.53.2 → ramses_rf-0.53.3}/tests/tests/parser_helpers/pkt_dev_class.log +0 -0
- {ramses_rf-0.53.2 → ramses_rf-0.53.3}/tests/tests/parsers/code_0001_wip.log +0 -0
- {ramses_rf-0.53.2 → ramses_rf-0.53.3}/tests/tests/parsers/code_0002.log +0 -0
- {ramses_rf-0.53.2 → ramses_rf-0.53.3}/tests/tests/parsers/code_0004_wip.log +0 -0
- {ramses_rf-0.53.2 → ramses_rf-0.53.3}/tests/tests/parsers/code_0005.log +0 -0
- {ramses_rf-0.53.2 → ramses_rf-0.53.3}/tests/tests/parsers/code_0006.log +0 -0
- {ramses_rf-0.53.2 → ramses_rf-0.53.3}/tests/tests/parsers/code_0008.log +0 -0
- {ramses_rf-0.53.2 → ramses_rf-0.53.3}/tests/tests/parsers/code_0009.log +0 -0
- {ramses_rf-0.53.2 → ramses_rf-0.53.3}/tests/tests/parsers/code_000a.log +0 -0
- {ramses_rf-0.53.2 → ramses_rf-0.53.3}/tests/tests/parsers/code_000c.log +0 -0
- {ramses_rf-0.53.2 → ramses_rf-0.53.3}/tests/tests/parsers/code_000e.log +0 -0
- {ramses_rf-0.53.2 → ramses_rf-0.53.3}/tests/tests/parsers/code_01ff_wip.log +0 -0
- {ramses_rf-0.53.2 → ramses_rf-0.53.3}/tests/tests/parsers/code_0418.log +0 -0
- {ramses_rf-0.53.2 → ramses_rf-0.53.3}/tests/tests/parsers/code_042f.log +0 -0
- {ramses_rf-0.53.2 → ramses_rf-0.53.3}/tests/tests/parsers/code_1030.log +0 -0
- {ramses_rf-0.53.2 → ramses_rf-0.53.3}/tests/tests/parsers/code_1060.log +0 -0
- {ramses_rf-0.53.2 → ramses_rf-0.53.3}/tests/tests/parsers/code_10d0.log +0 -0
- {ramses_rf-0.53.2 → ramses_rf-0.53.3}/tests/tests/parsers/code_10e0.log +0 -0
- {ramses_rf-0.53.2 → ramses_rf-0.53.3}/tests/tests/parsers/code_1260.log +0 -0
- {ramses_rf-0.53.2 → ramses_rf-0.53.3}/tests/tests/parsers/code_1298.log +0 -0
- {ramses_rf-0.53.2 → ramses_rf-0.53.3}/tests/tests/parsers/code_12a0.log +0 -0
- {ramses_rf-0.53.2 → ramses_rf-0.53.3}/tests/tests/parsers/code_12c0.log +0 -0
- {ramses_rf-0.53.2 → ramses_rf-0.53.3}/tests/tests/parsers/code_1300.log +0 -0
- {ramses_rf-0.53.2 → ramses_rf-0.53.3}/tests/tests/parsers/code_1f09.log +0 -0
- {ramses_rf-0.53.2 → ramses_rf-0.53.3}/tests/tests/parsers/code_1fc9.log +0 -0
- {ramses_rf-0.53.2 → ramses_rf-0.53.3}/tests/tests/parsers/code_1fd4.log +0 -0
- {ramses_rf-0.53.2 → ramses_rf-0.53.3}/tests/tests/parsers/code_2210.log +0 -0
- {ramses_rf-0.53.2 → ramses_rf-0.53.3}/tests/tests/parsers/code_22c9.log +0 -0
- {ramses_rf-0.53.2 → ramses_rf-0.53.3}/tests/tests/parsers/code_22d0.log +0 -0
- {ramses_rf-0.53.2 → ramses_rf-0.53.3}/tests/tests/parsers/code_22d9.log +0 -0
- {ramses_rf-0.53.2 → ramses_rf-0.53.3}/tests/tests/parsers/code_22e0.log +0 -0
- {ramses_rf-0.53.2 → ramses_rf-0.53.3}/tests/tests/parsers/code_22e5.log +0 -0
- {ramses_rf-0.53.2 → ramses_rf-0.53.3}/tests/tests/parsers/code_22e9.log +0 -0
- {ramses_rf-0.53.2 → ramses_rf-0.53.3}/tests/tests/parsers/code_22f1.log +0 -0
- {ramses_rf-0.53.2 → ramses_rf-0.53.3}/tests/tests/parsers/code_22f2.log +0 -0
- {ramses_rf-0.53.2 → ramses_rf-0.53.3}/tests/tests/parsers/code_22f3.log +0 -0
- {ramses_rf-0.53.2 → ramses_rf-0.53.3}/tests/tests/parsers/code_22f4.log +0 -0
- {ramses_rf-0.53.2 → ramses_rf-0.53.3}/tests/tests/parsers/code_22f7.log +0 -0
- {ramses_rf-0.53.2 → ramses_rf-0.53.3}/tests/tests/parsers/code_2309.log +0 -0
- {ramses_rf-0.53.2 → ramses_rf-0.53.3}/tests/tests/parsers/code_2349.log +0 -0
- {ramses_rf-0.53.2 → ramses_rf-0.53.3}/tests/tests/parsers/code_2411_wip.log +0 -0
- {ramses_rf-0.53.2 → ramses_rf-0.53.3}/tests/tests/parsers/code_2e04.log +0 -0
- {ramses_rf-0.53.2 → ramses_rf-0.53.3}/tests/tests/parsers/code_2e10_wip.log +0 -0
- {ramses_rf-0.53.2 → ramses_rf-0.53.3}/tests/tests/parsers/code_30c9.log +0 -0
- {ramses_rf-0.53.2 → ramses_rf-0.53.3}/tests/tests/parsers/code_3110_wip.log +0 -0
- {ramses_rf-0.53.2 → ramses_rf-0.53.3}/tests/tests/parsers/code_3120.log +0 -0
- {ramses_rf-0.53.2 → ramses_rf-0.53.3}/tests/tests/parsers/code_313e_wip.log +0 -0
- {ramses_rf-0.53.2 → ramses_rf-0.53.3}/tests/tests/parsers/code_3150.log +0 -0
- {ramses_rf-0.53.2 → ramses_rf-0.53.3}/tests/tests/parsers/code_31d9.log +0 -0
- {ramses_rf-0.53.2 → ramses_rf-0.53.3}/tests/tests/parsers/code_3200.log +0 -0
- {ramses_rf-0.53.2 → ramses_rf-0.53.3}/tests/tests/parsers/code_3210.log +0 -0
- {ramses_rf-0.53.2 → ramses_rf-0.53.3}/tests/tests/parsers/code_3220.log +0 -0
- {ramses_rf-0.53.2 → ramses_rf-0.53.3}/tests/tests/parsers/code_3222.log +0 -0
- {ramses_rf-0.53.2 → ramses_rf-0.53.3}/tests/tests/parsers/code_3ef0_wip.log +0 -0
- {ramses_rf-0.53.2 → ramses_rf-0.53.3}/tests/tests/parsers/code_3ef1_wip.log +0 -0
- {ramses_rf-0.53.2 → ramses_rf-0.53.3}/tests/tests/parsers/code_4e01.log +0 -0
- {ramses_rf-0.53.2 → ramses_rf-0.53.3}/tests/tests/parsers/code_4e02.log +0 -0
- {ramses_rf-0.53.2 → ramses_rf-0.53.3}/tests/tests/parsers/code_4e04.log +0 -0
- {ramses_rf-0.53.2 → ramses_rf-0.53.3}/tests/tests/parsers/code_4e15.log +0 -0
- {ramses_rf-0.53.2 → ramses_rf-0.53.3}/tests/tests/schedules/_sched_002/packet.log +0 -0
- {ramses_rf-0.53.2 → ramses_rf-0.53.3}/tests/tests/schedules/_sched_002/schedule.json +0 -0
- {ramses_rf-0.53.2 → ramses_rf-0.53.3}/tests/tests/schedules/sched_001/packet.log +0 -0
- {ramses_rf-0.53.2 → ramses_rf-0.53.3}/tests/tests/schedules/sched_001/schedule.json +0 -0
- {ramses_rf-0.53.2 → ramses_rf-0.53.3}/tests/tests/schedules/sched_dhw/packet.log +0 -0
- {ramses_rf-0.53.2 → ramses_rf-0.53.3}/tests/tests/schedules/sched_dhw/schedule.json +0 -0
- {ramses_rf-0.53.2 → ramses_rf-0.53.3}/tests/tests/schemas/jsn_files/schema_100.json +0 -0
- {ramses_rf-0.53.2 → ramses_rf-0.53.3}/tests/tests/schemas/jsn_files/schema_101.json +0 -0
- {ramses_rf-0.53.2 → ramses_rf-0.53.3}/tests/tests/schemas/jsn_files/schema_102.json +0 -0
- {ramses_rf-0.53.2 → ramses_rf-0.53.3}/tests/tests/schemas/jsn_files/schema_103.json +0 -0
- {ramses_rf-0.53.2 → ramses_rf-0.53.3}/tests/tests/schemas/jsn_files/schema_104.json +0 -0
- {ramses_rf-0.53.2 → ramses_rf-0.53.3}/tests/tests/schemas/jsn_files/schema_105.json +0 -0
- {ramses_rf-0.53.2 → ramses_rf-0.53.3}/tests/tests/schemas/jsn_files/schema_108.json +0 -0
- {ramses_rf-0.53.2 → ramses_rf-0.53.3}/tests/tests/schemas/log_files/schema_000.json +0 -0
- {ramses_rf-0.53.2 → ramses_rf-0.53.3}/tests/tests/schemas/log_files/schema_000.log +0 -0
- {ramses_rf-0.53.2 → ramses_rf-0.53.3}/tests/tests/schemas/log_files/schema_001.json +0 -0
- {ramses_rf-0.53.2 → ramses_rf-0.53.3}/tests/tests/schemas/log_files/schema_001.log +0 -0
- {ramses_rf-0.53.2 → ramses_rf-0.53.3}/tests/tests/schemas/log_files/schema_002.json +0 -0
- {ramses_rf-0.53.2 → ramses_rf-0.53.3}/tests/tests/schemas/log_files/schema_002.log +0 -0
- {ramses_rf-0.53.2 → ramses_rf-0.53.3}/tests/tests/schemas/log_files/schema_010.json +0 -0
- {ramses_rf-0.53.2 → ramses_rf-0.53.3}/tests/tests/schemas/log_files/schema_010.log +0 -0
- {ramses_rf-0.53.2 → ramses_rf-0.53.3}/tests/tests/schemas/log_files/schema_011.json +0 -0
- {ramses_rf-0.53.2 → ramses_rf-0.53.3}/tests/tests/schemas/log_files/schema_011.log +0 -0
- {ramses_rf-0.53.2 → ramses_rf-0.53.3}/tests/tests/schemas/log_files/schema_012.json +0 -0
- {ramses_rf-0.53.2 → ramses_rf-0.53.3}/tests/tests/schemas/log_files/schema_012.log +0 -0
- {ramses_rf-0.53.2 → ramses_rf-0.53.3}/tests/tests/schemas/log_files/schema_013.json +0 -0
- {ramses_rf-0.53.2 → ramses_rf-0.53.3}/tests/tests/schemas/log_files/schema_013.log +0 -0
- {ramses_rf-0.53.2 → ramses_rf-0.53.3}/tests/tests/schemas/log_files/schema_014.json +0 -0
- {ramses_rf-0.53.2 → ramses_rf-0.53.3}/tests/tests/schemas/log_files/schema_014.log +0 -0
- {ramses_rf-0.53.2 → ramses_rf-0.53.3}/tests/tests/schemas/log_files/schema_300.json +0 -0
- {ramses_rf-0.53.2 → ramses_rf-0.53.3}/tests/tests/schemas/log_files/schema_300.log +0 -0
- {ramses_rf-0.53.2 → ramses_rf-0.53.3}/tests/tests/schemas/log_files/schema_301.json +0 -0
- {ramses_rf-0.53.2 → ramses_rf-0.53.3}/tests/tests/schemas/log_files/schema_301.log +0 -0
- {ramses_rf-0.53.2 → ramses_rf-0.53.3}/tests/tests/schemas/log_files/schema_302.json +0 -0
- {ramses_rf-0.53.2 → ramses_rf-0.53.3}/tests/tests/schemas/log_files/schema_302.log +0 -0
- {ramses_rf-0.53.2 → ramses_rf-0.53.3}/tests/tests/schemas/log_files/schema_303.json +0 -0
- {ramses_rf-0.53.2 → ramses_rf-0.53.3}/tests/tests/schemas/log_files/schema_303.log +0 -0
- {ramses_rf-0.53.2 → ramses_rf-0.53.3}/tests/tests/schemas/log_files/schema_304.json +0 -0
- {ramses_rf-0.53.2 → ramses_rf-0.53.3}/tests/tests/schemas/log_files/schema_304.log +0 -0
- {ramses_rf-0.53.2 → ramses_rf-0.53.3}/tests/tests/schemas/log_files/schema_310.json +0 -0
- {ramses_rf-0.53.2 → ramses_rf-0.53.3}/tests/tests/schemas/log_files/schema_310.log +0 -0
- {ramses_rf-0.53.2 → ramses_rf-0.53.3}/tests/tests/systems/_heat_trv_00/config.json +0 -0
- {ramses_rf-0.53.2 → ramses_rf-0.53.3}/tests/tests/systems/_heat_trv_00/packet.log +0 -0
- {ramses_rf-0.53.2 → ramses_rf-0.53.3}/tests/tests/systems/_heat_trv_00/schema.json +0 -0
- {ramses_rf-0.53.2 → ramses_rf-0.53.3}/tests/tests/systems/_hvac_nuaire/config.json +0 -0
- {ramses_rf-0.53.2 → ramses_rf-0.53.3}/tests/tests/systems/_hvac_nuaire/known_list.json +0 -0
- {ramses_rf-0.53.2 → ramses_rf-0.53.3}/tests/tests/systems/_hvac_nuaire/packet.log +0 -0
- {ramses_rf-0.53.2 → ramses_rf-0.53.3}/tests/tests/systems/_hvac_nuaire/schema.json +0 -0
- {ramses_rf-0.53.2 → ramses_rf-0.53.3}/tests/tests/systems/_hvac_nuaire/status.json +0 -0
- {ramses_rf-0.53.2 → ramses_rf-0.53.3}/tests/tests/systems/heat_otb_00/config.json +0 -0
- {ramses_rf-0.53.2 → ramses_rf-0.53.3}/tests/tests/systems/heat_otb_00/packet.log +0 -0
- {ramses_rf-0.53.2 → ramses_rf-0.53.3}/tests/tests/systems/heat_otb_00/schema.json +0 -0
- {ramses_rf-0.53.2 → ramses_rf-0.53.3}/tests/tests/systems/heat_simple/packet.log +0 -0
- {ramses_rf-0.53.2 → ramses_rf-0.53.3}/tests/tests/systems/heat_simple/schema.json +0 -0
- {ramses_rf-0.53.2 → ramses_rf-0.53.3}/tests/tests/systems/heat_ufc_00/config.json +0 -0
- {ramses_rf-0.53.2 → ramses_rf-0.53.3}/tests/tests/systems/heat_ufc_00/packet.log +0 -0
- {ramses_rf-0.53.2 → ramses_rf-0.53.3}/tests/tests/systems/heat_ufc_01/packet.log +0 -0
- {ramses_rf-0.53.2 → ramses_rf-0.53.3}/tests/tests/systems/heat_zxdavb/config.json +0 -0
- {ramses_rf-0.53.2 → ramses_rf-0.53.3}/tests/tests/systems/heat_zxdavb/known_list.json +0 -0
- {ramses_rf-0.53.2 → ramses_rf-0.53.3}/tests/tests/systems/heat_zxdavb/packet.log +0 -0
- {ramses_rf-0.53.2 → ramses_rf-0.53.3}/tests/tests/systems/heat_zxdavb/schema.json +0 -0
- {ramses_rf-0.53.2 → ramses_rf-0.53.3}/tests/tests/test_api_faultlog.py +0 -0
- {ramses_rf-0.53.2 → ramses_rf-0.53.3}/tests/tests/test_api_schedule.py +0 -0
- {ramses_rf-0.53.2 → ramses_rf-0.53.3}/tests/tests/test_apis_binding.py +0 -0
- {ramses_rf-0.53.2 → ramses_rf-0.53.3}/tests/tests/test_apis_common.py +0 -0
- {ramses_rf-0.53.2 → ramses_rf-0.53.3}/tests/tests/test_apis_heat.py +0 -0
- {ramses_rf-0.53.2 → ramses_rf-0.53.3}/tests/tests/test_apis_hvac.py +0 -0
- {ramses_rf-0.53.2 → ramses_rf-0.53.3}/tests/tests/test_cli_transport_factory.py +0 -0
- {ramses_rf-0.53.2 → ramses_rf-0.53.3}/tests/tests/test_devices.py +0 -0
- {ramses_rf-0.53.2 → ramses_rf-0.53.3}/tests/tests/test_eavesdrop_dev_class.py +0 -0
- {ramses_rf-0.53.2 → ramses_rf-0.53.3}/tests/tests/test_eavesdrop_schema.py +0 -0
- {ramses_rf-0.53.2 → ramses_rf-0.53.3}/tests/tests/test_helpers.py +0 -0
- {ramses_rf-0.53.2 → ramses_rf-0.53.3}/tests/tests/test_parser_helpers.py +0 -0
- {ramses_rf-0.53.2 → ramses_rf-0.53.3}/tests/tests/test_parsers.py +0 -0
- {ramses_rf-0.53.2 → ramses_rf-0.53.3}/tests/tests/test_ramses_schema.py +0 -0
- {ramses_rf-0.53.2 → ramses_rf-0.53.3}/tests/tests/test_schema_bits.py +0 -0
- {ramses_rf-0.53.2 → ramses_rf-0.53.3}/tests/tests/test_schemas.py +0 -0
- {ramses_rf-0.53.2 → ramses_rf-0.53.3}/tests/tests/test_systems.py +0 -0
- {ramses_rf-0.53.2 → ramses_rf-0.53.3}/tests/tests/test_vol_schemas.py +0 -0
- {ramses_rf-0.53.2 → ramses_rf-0.53.3}/tests/tests_cli/test_cli_utility.py +0 -0
- {ramses_rf-0.53.2 → ramses_rf-0.53.3}/tests/tests_cli/test_client.py +0 -0
- {ramses_rf-0.53.2 → ramses_rf-0.53.3}/tests/tests_cli/test_debug.py +0 -0
- {ramses_rf-0.53.2 → ramses_rf-0.53.3}/tests/tests_cli/test_discovery.py +0 -0
- {ramses_rf-0.53.2 → ramses_rf-0.53.3}/tests/tests_rf/__init__.py +0 -0
- {ramses_rf-0.53.2 → ramses_rf-0.53.3}/tests/tests_rf/configs/config_heat.json +0 -0
- {ramses_rf-0.53.2 → ramses_rf-0.53.3}/tests/tests_rf/configs/config_hvac.json +0 -0
- {ramses_rf-0.53.2 → ramses_rf-0.53.3}/tests/tests_rf/conftest.py +0 -0
- {ramses_rf-0.53.2 → ramses_rf-0.53.3}/tests/tests_rf/device/__init__.py +0 -0
- {ramses_rf-0.53.2 → ramses_rf-0.53.3}/tests/tests_rf/device/test_hvac_ventilator.py +0 -0
- {ramses_rf-0.53.2 → ramses_rf-0.53.3}/tests/tests_rf/logs/test_api_faultlog.log +0 -0
- {ramses_rf-0.53.2 → ramses_rf-0.53.3}/tests/tests_rf/test_api_faultlog.py +0 -0
- {ramses_rf-0.53.2 → ramses_rf-0.53.3}/tests/tests_rf/test_api_schedule.py +0 -0
- {ramses_rf-0.53.2 → ramses_rf-0.53.3}/tests/tests_rf/test_binding_fsm.py +0 -0
- {ramses_rf-0.53.2 → ramses_rf-0.53.3}/tests/tests_rf/test_create_stack.py +0 -0
- {ramses_rf-0.53.2 → ramses_rf-0.53.3}/tests/tests_rf/test_dispatcher.py +0 -0
- {ramses_rf-0.53.2 → ramses_rf-0.53.3}/tests/tests_rf/test_entity_base.py +0 -0
- {ramses_rf-0.53.2 → ramses_rf-0.53.3}/tests/tests_rf/test_hgi_behaviors.py +0 -0
- {ramses_rf-0.53.2 → ramses_rf-0.53.3}/tests/tests_rf/test_protocol_fsm.py +0 -0
- {ramses_rf-0.53.2 → ramses_rf-0.53.3}/tests/tests_rf/test_use_regex.py +0 -0
- {ramses_rf-0.53.2 → ramses_rf-0.53.3}/tests/tests_rf/test_virt_network.py +0 -0
- {ramses_rf-0.53.2 → ramses_rf-0.53.3}/tests/tests_rf/test_virtual_rf.py +0 -0
- {ramses_rf-0.53.2 → ramses_rf-0.53.3}/tests/tests_rf/virtual_rf/__init__.py +0 -0
- {ramses_rf-0.53.2 → ramses_rf-0.53.3}/tests/tests_rf/virtual_rf/const.py +0 -0
- {ramses_rf-0.53.2 → ramses_rf-0.53.3}/tests/tests_rf/virtual_rf/helpers.py +0 -0
- {ramses_rf-0.53.2 → ramses_rf-0.53.3}/tests/tests_rf/virtual_rf/virtual_rf.py +0 -0
- {ramses_rf-0.53.2 → ramses_rf-0.53.3}/tests/tests_tx/__init__.py +0 -0
- {ramses_rf-0.53.2 → ramses_rf-0.53.3}/tests/tests_tx/test_command.py +0 -0
- {ramses_rf-0.53.2 → ramses_rf-0.53.3}/tests/tests_tx/test_const.py +0 -0
- {ramses_rf-0.53.2 → ramses_rf-0.53.3}/tests/wip/_test_eavesdrop_dhw_sensor.py +0 -0
- {ramses_rf-0.53.2 → ramses_rf-0.53.3}/tests/wip/_test_eavesdrop_htg_control.py +0 -0
- {ramses_rf-0.53.2 → ramses_rf-0.53.3}/tests/wip/_test_eavesdrop_ufc_circuits.py +0 -0
- {ramses_rf-0.53.2 → ramses_rf-0.53.3}/tests/wip/_test_eavesdrop_zone_sensors.py +0 -0
- {ramses_rf-0.53.2 → ramses_rf-0.53.3}/tests/wip/_test_eavesdrop_zone_type.py +0 -0
- {ramses_rf-0.53.2 → ramses_rf-0.53.3}/tests/wip/test_wip_cli.sh +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: ramses_rf
|
|
3
|
-
Version: 0.53.
|
|
3
|
+
Version: 0.53.3
|
|
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
|
|
@@ -24,14 +24,19 @@ RAMSES RF - Message database and index.
|
|
|
24
24
|
from __future__ import annotations
|
|
25
25
|
|
|
26
26
|
import asyncio
|
|
27
|
+
import contextlib
|
|
27
28
|
import logging
|
|
29
|
+
import os
|
|
28
30
|
import sqlite3
|
|
31
|
+
import uuid
|
|
29
32
|
from collections import OrderedDict
|
|
30
33
|
from datetime import datetime as dt, timedelta as td
|
|
31
34
|
from typing import TYPE_CHECKING, Any, NewType
|
|
32
35
|
|
|
33
36
|
from ramses_tx import CODES_SCHEMA, RQ, Code, Message, Packet
|
|
34
37
|
|
|
38
|
+
from .storage import StorageWorker
|
|
39
|
+
|
|
35
40
|
if TYPE_CHECKING:
|
|
36
41
|
DtmStrT = NewType("DtmStrT", str)
|
|
37
42
|
MsgDdT = OrderedDict[DtmStrT, Message]
|
|
@@ -89,22 +94,55 @@ class MessageIndex:
|
|
|
89
94
|
|
|
90
95
|
_housekeeping_task: asyncio.Task[None]
|
|
91
96
|
|
|
92
|
-
def __init__(self, maintain: bool = True) -> None:
|
|
97
|
+
def __init__(self, maintain: bool = True, db_path: str = ":memory:") -> None:
|
|
93
98
|
"""Instantiate a message database/index."""
|
|
94
99
|
|
|
95
100
|
self.maintain = maintain
|
|
96
101
|
self._msgs: MsgDdT = OrderedDict() # stores all messages for retrieval.
|
|
97
102
|
# Filled & cleaned up in housekeeping_loop.
|
|
98
103
|
|
|
99
|
-
#
|
|
104
|
+
# For :memory: databases with multiple connections (Reader vs Worker)
|
|
105
|
+
# We must use a Shared Cache URI so both threads see the same data.
|
|
106
|
+
if db_path == ":memory:":
|
|
107
|
+
# Unique ID ensures parallel tests don't share the same in-memory DB
|
|
108
|
+
db_path = f"file:ramses_rf_{uuid.uuid4()}?mode=memory&cache=shared"
|
|
109
|
+
|
|
110
|
+
# Start the Storage Worker (Write Connection)
|
|
111
|
+
# This thread handles all blocking INSERT/UPDATE operations
|
|
112
|
+
self._worker = StorageWorker(db_path)
|
|
113
|
+
|
|
114
|
+
# Wait for the worker to create the tables.
|
|
115
|
+
# This prevents "no such table" errors on immediate reads.
|
|
116
|
+
if not self._worker.wait_for_ready(timeout=10.0):
|
|
117
|
+
_LOGGER.error("MessageIndex: StorageWorker timed out initializing database")
|
|
118
|
+
|
|
119
|
+
# Connect to a SQLite DB (Read Connection)
|
|
100
120
|
self._cx = sqlite3.connect(
|
|
101
|
-
|
|
121
|
+
db_path,
|
|
122
|
+
detect_types=sqlite3.PARSE_DECLTYPES | sqlite3.PARSE_COLNAMES,
|
|
123
|
+
check_same_thread=False,
|
|
124
|
+
uri=True, # Enable URI parsing for shared memory support
|
|
125
|
+
timeout=10.0, # Increased timeout to reduce 'database locked' errors
|
|
126
|
+
isolation_level=None, # Autocommit mode prevents stale snapshots
|
|
102
127
|
)
|
|
128
|
+
|
|
129
|
+
# Enable Write-Ahead Logging for Reader as well
|
|
130
|
+
if db_path != ":memory:" and "mode=memory" not in db_path:
|
|
131
|
+
with contextlib.suppress(sqlite3.Error):
|
|
132
|
+
self._cx.execute("PRAGMA journal_mode=WAL")
|
|
133
|
+
elif "cache=shared" in db_path:
|
|
134
|
+
# Shared cache (used in tests) requires read_uncommitted to prevent
|
|
135
|
+
# readers from blocking writers (Table Locking).
|
|
136
|
+
with contextlib.suppress(sqlite3.Error):
|
|
137
|
+
self._cx.execute("PRAGMA read_uncommitted = true")
|
|
138
|
+
|
|
103
139
|
# detect_types should retain dt type on store/retrieve
|
|
104
140
|
self._cu = self._cx.cursor() # Create a cursor
|
|
105
141
|
|
|
106
142
|
_setup_db_adapters() # DTM adapter/converter
|
|
107
|
-
|
|
143
|
+
|
|
144
|
+
# Schema creation is now handled safely by the StorageWorker to avoid races.
|
|
145
|
+
# self._setup_db_schema()
|
|
108
146
|
|
|
109
147
|
if self.maintain:
|
|
110
148
|
self._lock = asyncio.Lock()
|
|
@@ -137,6 +175,7 @@ class MessageIndex:
|
|
|
137
175
|
):
|
|
138
176
|
self._housekeeping_task.cancel() # stop the housekeeper
|
|
139
177
|
|
|
178
|
+
self._worker.stop() # Stop the background thread
|
|
140
179
|
self._cx.commit() # just in case
|
|
141
180
|
self._cx.close() # may still need to do queries after engine has stopped?
|
|
142
181
|
|
|
@@ -145,6 +184,13 @@ class MessageIndex:
|
|
|
145
184
|
"""Return the messages in the index in a threadsafe way."""
|
|
146
185
|
return self._msgs
|
|
147
186
|
|
|
187
|
+
def flush(self) -> None:
|
|
188
|
+
"""Flush the storage worker queue.
|
|
189
|
+
|
|
190
|
+
This is primarily for testing to ensure data persistence before querying.
|
|
191
|
+
"""
|
|
192
|
+
self._worker.flush()
|
|
193
|
+
|
|
148
194
|
def _setup_db_schema(self) -> None:
|
|
149
195
|
"""Set up the message database schema.
|
|
150
196
|
|
|
@@ -236,23 +282,30 @@ class MessageIndex:
|
|
|
236
282
|
dup: tuple[Message, ...] = tuple() # avoid UnboundLocalError
|
|
237
283
|
old: Message | None = None # avoid UnboundLocalError
|
|
238
284
|
|
|
285
|
+
# Check in-memory cache for collision instead of blocking SQL
|
|
286
|
+
dtm_str: DtmStrT = msg.dtm.isoformat(timespec="microseconds") # type: ignore[assignment]
|
|
287
|
+
if dtm_str in self._msgs:
|
|
288
|
+
dup = (self._msgs[dtm_str],)
|
|
289
|
+
|
|
239
290
|
try: # TODO: remove this, or apply only when source is a real packet log?
|
|
240
291
|
# await self._lock.acquire()
|
|
241
|
-
dup = self._delete_from( # HACK: because of contrived pkt logs
|
|
242
|
-
|
|
243
|
-
)
|
|
244
|
-
|
|
292
|
+
# dup = self._delete_from( # HACK: because of contrived pkt logs
|
|
293
|
+
# dtm=msg.dtm # stored as such with DTM formatter
|
|
294
|
+
# )
|
|
295
|
+
# We defer the write to the worker; return value (old) is not available synchronously
|
|
296
|
+
self._insert_into(msg) # will delete old msg by hdr (not dtm!)
|
|
245
297
|
|
|
246
298
|
except (
|
|
247
299
|
sqlite3.Error
|
|
248
300
|
): # UNIQUE constraint failed: ? messages.dtm or .hdr (so: HACK)
|
|
249
|
-
self._cx.rollback()
|
|
301
|
+
# self._cx.rollback()
|
|
302
|
+
pass
|
|
250
303
|
|
|
251
304
|
else:
|
|
252
305
|
# _msgs dict requires a timestamp reformat
|
|
253
|
-
dtm: DtmStrT = msg.dtm.isoformat(timespec="microseconds")
|
|
306
|
+
# dtm: DtmStrT = msg.dtm.isoformat(timespec="microseconds")
|
|
254
307
|
# add msg to self._msgs dict
|
|
255
|
-
self._msgs[
|
|
308
|
+
self._msgs[dtm_str] = msg
|
|
256
309
|
|
|
257
310
|
finally:
|
|
258
311
|
pass # self._lock.release()
|
|
@@ -288,39 +341,36 @@ class MessageIndex:
|
|
|
288
341
|
dtm: DtmStrT = _now.isoformat(timespec="microseconds") # type: ignore[assignment]
|
|
289
342
|
hdr = f"{code}|{verb}|{src}|{payload}"
|
|
290
343
|
|
|
291
|
-
dup = self._delete_from(hdr=hdr)
|
|
344
|
+
# dup = self._delete_from(hdr=hdr)
|
|
345
|
+
# Avoid blocking read; worker handles REPLACE on unique constraint collision
|
|
346
|
+
|
|
347
|
+
# Prepare data tuple for worker
|
|
348
|
+
data = (
|
|
349
|
+
_now,
|
|
350
|
+
verb,
|
|
351
|
+
src,
|
|
352
|
+
src,
|
|
353
|
+
code,
|
|
354
|
+
None,
|
|
355
|
+
hdr,
|
|
356
|
+
"|",
|
|
357
|
+
)
|
|
292
358
|
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
self.
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
code,
|
|
306
|
-
None,
|
|
307
|
-
hdr,
|
|
308
|
-
"|",
|
|
309
|
-
),
|
|
310
|
-
)
|
|
311
|
-
except sqlite3.Error:
|
|
312
|
-
self._cx.rollback()
|
|
313
|
-
else:
|
|
314
|
-
# also add dummy 3220 msg to self._msgs dict to allow maintenance loop
|
|
315
|
-
msg: Message = Message._from_pkt(
|
|
316
|
-
Packet(
|
|
317
|
-
_now, f"... {verb} --- {src} --:------ {src} {code} 005 0000000000"
|
|
318
|
-
)
|
|
319
|
-
)
|
|
320
|
-
self._msgs[dtm] = msg
|
|
359
|
+
self._worker.submit_packet(data)
|
|
360
|
+
|
|
361
|
+
# Backward compatibility for Tests:
|
|
362
|
+
# Check specific env var set by pytest, which is more reliable than sys.modules
|
|
363
|
+
if "PYTEST_CURRENT_TEST" in os.environ:
|
|
364
|
+
self.flush()
|
|
365
|
+
|
|
366
|
+
# also add dummy 3220 msg to self._msgs dict to allow maintenance loop
|
|
367
|
+
msg: Message = Message._from_pkt(
|
|
368
|
+
Packet(_now, f"... {verb} --- {src} --:------ {src} {code} 005 0000000000")
|
|
369
|
+
)
|
|
370
|
+
self._msgs[dtm] = msg
|
|
321
371
|
|
|
322
|
-
if dup: # expected when more than one heat system in schema
|
|
323
|
-
|
|
372
|
+
# if dup: # expected when more than one heat system in schema
|
|
373
|
+
# _LOGGER.debug("Replaced record with same hdr: %s", hdr)
|
|
324
374
|
|
|
325
375
|
def _insert_into(self, msg: Message) -> Message | None:
|
|
326
376
|
"""
|
|
@@ -337,29 +387,31 @@ class MessageIndex:
|
|
|
337
387
|
else:
|
|
338
388
|
msg_pkt_ctx = msg._pkt._ctx # can be None
|
|
339
389
|
|
|
340
|
-
_old_msgs = self._delete_from(hdr=msg._pkt._hdr)
|
|
390
|
+
# _old_msgs = self._delete_from(hdr=msg._pkt._hdr)
|
|
391
|
+
# Refactor: Worker uses INSERT OR REPLACE to handle collision
|
|
392
|
+
|
|
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),
|
|
402
|
+
)
|
|
341
403
|
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
404
|
+
self._worker.submit_packet(data)
|
|
405
|
+
|
|
406
|
+
# Backward compatibility for Tests:
|
|
407
|
+
# Tests assume the DB update is instant. If running in pytest, flush immediately.
|
|
408
|
+
# This effectively makes the operation synchronous during tests to avoid rewriting tests.
|
|
409
|
+
if "PYTEST_CURRENT_TEST" in os.environ:
|
|
410
|
+
self.flush()
|
|
346
411
|
|
|
347
|
-
self._cu.execute(
|
|
348
|
-
sql,
|
|
349
|
-
(
|
|
350
|
-
msg.dtm,
|
|
351
|
-
str(msg.verb),
|
|
352
|
-
msg.src.id,
|
|
353
|
-
msg.dst.id,
|
|
354
|
-
str(msg.code),
|
|
355
|
-
msg_pkt_ctx,
|
|
356
|
-
msg._pkt._hdr,
|
|
357
|
-
payload_keys(msg.payload),
|
|
358
|
-
),
|
|
359
|
-
)
|
|
360
412
|
# _LOGGER.debug(f"Added {msg} to gwy.msg_db")
|
|
361
413
|
|
|
362
|
-
return
|
|
414
|
+
return None
|
|
363
415
|
|
|
364
416
|
def rem(
|
|
365
417
|
self, msg: Message | None = None, **kwargs: str | dt
|
|
@@ -0,0 +1,168 @@
|
|
|
1
|
+
"""RAMSES RF - Background storage worker for async I/O."""
|
|
2
|
+
|
|
3
|
+
from __future__ import annotations
|
|
4
|
+
|
|
5
|
+
import contextlib
|
|
6
|
+
import logging
|
|
7
|
+
import queue
|
|
8
|
+
import sqlite3
|
|
9
|
+
import threading
|
|
10
|
+
from typing import Any
|
|
11
|
+
|
|
12
|
+
_LOGGER = logging.getLogger(__name__)
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
class StorageWorker:
|
|
16
|
+
"""A background worker thread to handle blocking storage I/O asynchronously."""
|
|
17
|
+
|
|
18
|
+
def __init__(self, db_path: str = ":memory:"):
|
|
19
|
+
"""Initialize the storage worker thread."""
|
|
20
|
+
self._db_path = db_path
|
|
21
|
+
self._queue: queue.SimpleQueue[tuple[str, Any] | None] = queue.SimpleQueue()
|
|
22
|
+
self._ready_event = threading.Event()
|
|
23
|
+
|
|
24
|
+
self._thread = threading.Thread(
|
|
25
|
+
target=self._run,
|
|
26
|
+
name="RamsesStorage",
|
|
27
|
+
daemon=True, # FIX: Set to True so the process can exit even if stop() is missed
|
|
28
|
+
)
|
|
29
|
+
self._thread.start()
|
|
30
|
+
|
|
31
|
+
def wait_for_ready(self, timeout: float | None = None) -> bool:
|
|
32
|
+
"""Wait until the database is initialized and ready."""
|
|
33
|
+
return self._ready_event.wait(timeout)
|
|
34
|
+
|
|
35
|
+
def submit_packet(self, packet_data: tuple[Any, ...]) -> None:
|
|
36
|
+
"""Submit a packet tuple for SQL insertion (Non-blocking)."""
|
|
37
|
+
self._queue.put(("SQL", packet_data))
|
|
38
|
+
|
|
39
|
+
def flush(self, timeout: float = 10.0) -> None:
|
|
40
|
+
"""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
|
+
# We inject a special marker into the queue
|
|
46
|
+
sentinel = threading.Event()
|
|
47
|
+
self._queue.put(("MARKER", sentinel))
|
|
48
|
+
|
|
49
|
+
# Wait for the worker to set the sentinel
|
|
50
|
+
if not sentinel.wait(timeout):
|
|
51
|
+
_LOGGER.warning("StorageWorker flush timed out")
|
|
52
|
+
|
|
53
|
+
def stop(self) -> None:
|
|
54
|
+
"""Signal the worker to stop processing and close resources."""
|
|
55
|
+
self._queue.put(None) # Poison pill
|
|
56
|
+
self._thread.join()
|
|
57
|
+
|
|
58
|
+
def _init_db(self, conn: sqlite3.Connection) -> None:
|
|
59
|
+
"""Initialize the database schema."""
|
|
60
|
+
cursor = conn.cursor()
|
|
61
|
+
cursor.execute(
|
|
62
|
+
"""
|
|
63
|
+
CREATE TABLE IF NOT EXISTS messages (
|
|
64
|
+
dtm DTM NOT NULL PRIMARY KEY,
|
|
65
|
+
verb TEXT(2) NOT NULL,
|
|
66
|
+
src TEXT(12) NOT NULL,
|
|
67
|
+
dst TEXT(12) NOT NULL,
|
|
68
|
+
code TEXT(4) NOT NULL,
|
|
69
|
+
ctx TEXT,
|
|
70
|
+
hdr TEXT NOT NULL UNIQUE,
|
|
71
|
+
plk TEXT NOT NULL
|
|
72
|
+
)
|
|
73
|
+
"""
|
|
74
|
+
)
|
|
75
|
+
# Create indexes to speed up future reads
|
|
76
|
+
for col in ("verb", "src", "dst", "code", "ctx", "hdr"):
|
|
77
|
+
cursor.execute(f"CREATE INDEX IF NOT EXISTS idx_{col} ON messages ({col})")
|
|
78
|
+
conn.commit()
|
|
79
|
+
|
|
80
|
+
def _run(self) -> None:
|
|
81
|
+
"""The main loop running in the background thread."""
|
|
82
|
+
_LOGGER.debug("StorageWorker thread started.")
|
|
83
|
+
|
|
84
|
+
# Setup SQLite connection in this thread
|
|
85
|
+
try:
|
|
86
|
+
# uri=True allows opening "file::memory:?cache=shared"
|
|
87
|
+
conn = sqlite3.connect(
|
|
88
|
+
self._db_path,
|
|
89
|
+
detect_types=sqlite3.PARSE_DECLTYPES | sqlite3.PARSE_COLNAMES,
|
|
90
|
+
check_same_thread=False,
|
|
91
|
+
uri=True,
|
|
92
|
+
timeout=10.0, # Increased timeout for locking
|
|
93
|
+
)
|
|
94
|
+
|
|
95
|
+
# Enable Write-Ahead Logging for concurrency
|
|
96
|
+
if self._db_path != ":memory:" and "mode=memory" not in self._db_path:
|
|
97
|
+
with contextlib.suppress(sqlite3.Error):
|
|
98
|
+
conn.execute("PRAGMA journal_mode=WAL")
|
|
99
|
+
conn.execute("PRAGMA synchronous=NORMAL")
|
|
100
|
+
elif "cache=shared" in self._db_path:
|
|
101
|
+
with contextlib.suppress(sqlite3.Error):
|
|
102
|
+
conn.execute("PRAGMA read_uncommitted = true")
|
|
103
|
+
|
|
104
|
+
self._init_db(conn)
|
|
105
|
+
self._ready_event.set() # Signal that tables exist
|
|
106
|
+
except sqlite3.Error as exc:
|
|
107
|
+
_LOGGER.error("Failed to initialize storage database: %s", exc)
|
|
108
|
+
self._ready_event.set() # Avoid blocking waiters forever
|
|
109
|
+
return
|
|
110
|
+
|
|
111
|
+
while True:
|
|
112
|
+
try:
|
|
113
|
+
# Block here waiting for work
|
|
114
|
+
item = self._queue.get()
|
|
115
|
+
|
|
116
|
+
if item is None: # Shutdown signal
|
|
117
|
+
break
|
|
118
|
+
|
|
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":
|
|
127
|
+
# Optimization: Batch processing
|
|
128
|
+
batch = [data]
|
|
129
|
+
# Drain queue of pending SQL tasks to bulk insert
|
|
130
|
+
while not self._queue.empty():
|
|
131
|
+
try:
|
|
132
|
+
# Peek/get next item without blocking
|
|
133
|
+
next_item = self._queue.get_nowait()
|
|
134
|
+
if next_item is None:
|
|
135
|
+
self._queue.put(None) # Re-queue poison pill
|
|
136
|
+
break
|
|
137
|
+
|
|
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
|
|
145
|
+
else:
|
|
146
|
+
pass
|
|
147
|
+
except queue.Empty:
|
|
148
|
+
break
|
|
149
|
+
|
|
150
|
+
try:
|
|
151
|
+
conn.executemany(
|
|
152
|
+
"""
|
|
153
|
+
INSERT OR REPLACE INTO messages
|
|
154
|
+
(dtm, verb, src, dst, code, ctx, hdr, plk)
|
|
155
|
+
VALUES (?, ?, ?, ?, ?, ?, ?, ?)
|
|
156
|
+
""",
|
|
157
|
+
batch,
|
|
158
|
+
)
|
|
159
|
+
conn.commit()
|
|
160
|
+
except sqlite3.Error as err:
|
|
161
|
+
_LOGGER.error("SQL Write Failed: %s", err)
|
|
162
|
+
|
|
163
|
+
except Exception as err:
|
|
164
|
+
_LOGGER.exception("StorageWorker encountered an error: %s", err)
|
|
165
|
+
|
|
166
|
+
# Cleanup
|
|
167
|
+
conn.close()
|
|
168
|
+
_LOGGER.debug("StorageWorker thread stopped.")
|
|
@@ -3109,7 +3109,9 @@ def parser_31da(payload: str, msg: Message) -> PayDictT._31DA:
|
|
|
3109
3109
|
if len(payload) == 58:
|
|
3110
3110
|
return result # type: ignore[return-value]
|
|
3111
3111
|
|
|
3112
|
-
result.update(
|
|
3112
|
+
result.update(
|
|
3113
|
+
{"_extra": payload[58:]}
|
|
3114
|
+
) # sporadic [58:60] one of {00, 20, 40} version?
|
|
3113
3115
|
return result # type: ignore[return-value]
|
|
3114
3116
|
|
|
3115
3117
|
# From an Orcon 15RF Display
|
|
@@ -551,7 +551,7 @@ CODES_SCHEMA: dict[Code, dict[str, Any]] = { # rf_unknown
|
|
|
551
551
|
},
|
|
552
552
|
Code._31DA: { # hvac_state (fan_state_extended)
|
|
553
553
|
SZ_NAME: "hvac_state",
|
|
554
|
-
I_: r"^(00|01|15|16|17|21)[0-9A-F]{56}(00|20)?$",
|
|
554
|
+
I_: r"^(00|01|15|16|17|21)[0-9A-F]{56}(00|20|40)?$",
|
|
555
555
|
RQ: r"^(00|01|15|16|17|21)$",
|
|
556
556
|
# RQ --- 32:168090 30:082155 --:------ 31DA 001 21
|
|
557
557
|
},
|
|
@@ -49,6 +49,7 @@ import logging
|
|
|
49
49
|
import os
|
|
50
50
|
import re
|
|
51
51
|
import sys
|
|
52
|
+
import time
|
|
52
53
|
from collections import deque
|
|
53
54
|
from collections.abc import Awaitable, Callable, Iterable
|
|
54
55
|
from datetime import datetime as dt, timedelta as td
|
|
@@ -988,7 +989,8 @@ class FileTransport(_ReadTransport, _FileTransportAbstractor):
|
|
|
988
989
|
"""Start the reader task."""
|
|
989
990
|
self._reading = True
|
|
990
991
|
try:
|
|
991
|
-
await self._reader()
|
|
992
|
+
# await self._reader()
|
|
993
|
+
await self.loop.run_in_executor(None, self._blocking_reader)
|
|
992
994
|
except Exception as err:
|
|
993
995
|
self.loop.call_soon_threadsafe(
|
|
994
996
|
functools.partial(self._protocol.connection_lost, err) # type: ignore[arg-type]
|
|
@@ -998,50 +1000,48 @@ class FileTransport(_ReadTransport, _FileTransportAbstractor):
|
|
|
998
1000
|
functools.partial(self._protocol.connection_lost, None)
|
|
999
1001
|
)
|
|
1000
1002
|
|
|
1001
|
-
|
|
1002
|
-
async def _reader(self) -> None: # TODO
|
|
1003
|
+
def _blocking_reader(self) -> None:
|
|
1003
1004
|
"""Loop through the packet source for Frames and process them."""
|
|
1004
1005
|
|
|
1005
1006
|
if isinstance(self._pkt_source, dict):
|
|
1006
1007
|
for dtm_str, pkt_line in self._pkt_source.items(): # assume dtm_str is OK
|
|
1007
|
-
|
|
1008
|
-
await asyncio.sleep(0.001)
|
|
1009
|
-
self._frame_read(dtm_str, pkt_line)
|
|
1010
|
-
await asyncio.sleep(0)
|
|
1011
|
-
# NOTE: instable without, big performance penalty if delay >0
|
|
1008
|
+
self._process_line(dtm_str, pkt_line)
|
|
1012
1009
|
|
|
1013
1010
|
elif isinstance(self._pkt_source, str): # file_name, used in client parse
|
|
1014
1011
|
# open file file_name before reading
|
|
1015
1012
|
try:
|
|
1016
1013
|
with fileinput.input(files=self._pkt_source, encoding="utf-8") as file:
|
|
1017
1014
|
for dtm_pkt_line in file: # self._pkt_source:
|
|
1018
|
-
|
|
1019
|
-
while not self._reading:
|
|
1020
|
-
await asyncio.sleep(0.001)
|
|
1021
|
-
# there may be blank lines in annotated log files
|
|
1022
|
-
if (dtm_pkt_line := dtm_pkt_line.strip()) and dtm_pkt_line[
|
|
1023
|
-
:1
|
|
1024
|
-
] != "#":
|
|
1025
|
-
self._frame_read(dtm_pkt_line[:26], dtm_pkt_line[27:])
|
|
1026
|
-
# this is where the parsing magic happens!
|
|
1027
|
-
await asyncio.sleep(0)
|
|
1028
|
-
# NOTE: instable without, big performance penalty if delay >0
|
|
1015
|
+
self._process_line_from_raw(dtm_pkt_line)
|
|
1029
1016
|
except FileNotFoundError as err:
|
|
1030
1017
|
_LOGGER.warning(f"Correct the packet file name; {err}")
|
|
1018
|
+
|
|
1031
1019
|
elif isinstance(self._pkt_source, TextIOWrapper): # used by client monitor
|
|
1032
1020
|
for dtm_pkt_line in self._pkt_source: # should check dtm_str is OK
|
|
1033
|
-
|
|
1034
|
-
|
|
1035
|
-
# can be blank lines in annotated log files
|
|
1036
|
-
if (dtm_pkt_line := dtm_pkt_line.strip()) and dtm_pkt_line[:1] != "#":
|
|
1037
|
-
self._frame_read(dtm_pkt_line[:26], dtm_pkt_line[27:])
|
|
1038
|
-
await asyncio.sleep(0)
|
|
1039
|
-
# NOTE: instable without, big performance penalty if delay >0
|
|
1021
|
+
self._process_line_from_raw(dtm_pkt_line)
|
|
1022
|
+
|
|
1040
1023
|
else:
|
|
1041
1024
|
raise exc.TransportSourceInvalid(
|
|
1042
1025
|
f"Packet source is not dict, TextIOWrapper or str: {self._pkt_source:!r}"
|
|
1043
1026
|
)
|
|
1044
1027
|
|
|
1028
|
+
def _process_line_from_raw(self, line: str) -> None:
|
|
1029
|
+
"""Helper to process raw lines."""
|
|
1030
|
+
# there may be blank lines in annotated log files
|
|
1031
|
+
if (line := line.strip()) and line[:1] != "#":
|
|
1032
|
+
self._process_line(line[:26], line[27:])
|
|
1033
|
+
# this is where the parsing magic happens!
|
|
1034
|
+
|
|
1035
|
+
def _process_line(self, dtm_str: str, frame: str) -> None:
|
|
1036
|
+
"""Push frame to protocol in a thread-safe way."""
|
|
1037
|
+
while not self._reading:
|
|
1038
|
+
time.sleep(0.001)
|
|
1039
|
+
|
|
1040
|
+
self._frame_read(dtm_str, frame)
|
|
1041
|
+
|
|
1042
|
+
# NOTE: instable without, big performance penalty if delay >0
|
|
1043
|
+
time.sleep(0)
|
|
1044
|
+
|
|
1045
1045
|
def _close(self, exc: exc.RamsesException | None = None) -> None:
|
|
1046
1046
|
"""Close the transport (cancel any outstanding tasks).
|
|
1047
1047
|
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
# Requirements to build the code documentation from the source code
|
|
2
|
+
# - last checked/updated: 2026-01-19 (c.f. HA 2026.1.2)
|
|
3
|
+
|
|
4
|
+
# libraries required to build with sphinx
|
|
5
|
+
# - pip list | grep -E 'sphinx'
|
|
6
|
+
|
|
7
|
+
# used for generating docs
|
|
8
|
+
# (Note: sphinx <10 for furo 2025.12.19 and sphinx_design 0.7.0)
|
|
9
|
+
furo==2025.12.19
|
|
10
|
+
markdown-it-py==4.0.0
|
|
11
|
+
myst-parser==5.0.0
|
|
12
|
+
Sphinx==9.1.0
|
|
13
|
+
sphinxcontrib-mermaid==2.0.0
|
|
14
|
+
sphinx-basic-ng==1.0.0b2
|
|
15
|
+
sphinx_design==0.7.0
|
|
@@ -300,6 +300,13 @@
|
|
|
300
300
|
# Siber DF EVO 2
|
|
301
301
|
2024-06-21T04:47:19.545913 ... I --- 32:137185 --:------ 32:137185 31DA 030 00EF007FFFEFEF080607D809480737F002AA02344000005CEF7FFF7FFF00 # {'hvac_id': '00', 'exhaust_fan_speed': 0.26, 'fan_info': 'speed 2, medium', '_unknown_fan_info_flags': [0, 0, 0], 'air_quality': None, 'co2_level': None, 'indoor_humidity': None, 'outdoor_humidity': None, 'exhaust_temp': 20.54, 'supply_temp': 20.08, 'indoor_temp': 23.76, 'outdoor_temp': 18.47, 'speed_capabilities': ['off', 'low_med_high', 'timer', 'boost', 'post_heater'], 'bypass_position': 0.85, 'supply_fan_speed': 0.32, 'remaining_mins': 0, 'post_heat': 0.46, 'pre_heat': None, 'supply_flow': None, 'exhaust_flow': None, '_extra': '00'}
|
|
302
302
|
2024-06-21T04:49:59.398298 ... I --- 32:137185 --:------ 32:137185 31DA 030 00EF007FFFEFEF086C07CC09380730F002A0023440000068EF7FFF7FFF00 # {'hvac_id': '00', 'exhaust_fan_speed': 0.26, 'fan_info': 'speed 2, medium', '_unknown_fan_info_flags': [0, 0, 0], 'air_quality': None, 'co2_level': None, 'indoor_humidity': None, 'outdoor_humidity': None, 'exhaust_temp': 21.56, 'supply_temp': 19.96, 'indoor_temp': 23.60, 'outdoor_temp': 18.40, 'speed_capabilities': ['off', 'low_med_high', 'timer', 'boost', 'post_heater'], 'bypass_position': 0.80, 'supply_fan_speed': 0.32, 'remaining_mins': 0, 'post_heat': 0.52, 'pre_heat': None, 'supply_flow': None, 'exhaust_flow': None, '_extra': '00'}
|
|
303
|
+
# Siber DF EVO 2, 2026 version _extra = 40
|
|
304
|
+
2026-01-15 12:44:19.792000 ... I --- 32:137185 --:------ 32:137185 31DA 030 00EF007FFFEFEF070D0789074B0603F00200035C6C0000AAEF7FFF7FFF40 # {'hvac_id': '00', 'exhaust_fan_speed': 0.46, 'fan_info': 'speed 3, high', '_unknown_fan_info_flags': [0, 0, 0], 'air_quality': None, 'co2_level': None, 'indoor_humidity': None, 'outdoor_humidity': None, 'exhaust_temp': 18.05, 'supply_temp': 19.29, 'indoor_temp': 18.67, 'outdoor_temp': 15.39, 'speed_capabilities': ['off', 'low_med_high', 'timer', 'boost', 'post_heater'], 'bypass_position': 0.0, 'supply_fan_speed': 0.54, 'remaining_mins': 0, 'post_heat': 0.85, 'pre_heat': None, 'supply_flow': None, 'exhaust_flow': None, '_extra': '40'}
|
|
305
|
+
2026-01-15 12:52:27.266000 ... RP --- 32:137185 37:145236 --:------ 31DA 030 00EF007FFFEFEF070A0786074905FEF00200035C6C0000ADEF7FFF7FFF40 # {'hvac_id': '00', 'exhaust_fan_speed': 0.46, 'fan_info': 'speed 3, high', '_unknown_fan_info_flags': [0, 0, 0], 'air_quality': None, 'co2_level': None, 'indoor_humidity': None, 'outdoor_humidity': None, 'exhaust_temp': 18.02, 'supply_temp': 19.26, 'indoor_temp': 18.65, 'outdoor_temp': 15.34, 'speed_capabilities': ['off', 'low_med_high', 'timer', 'boost', 'post_heater'], 'bypass_position': 0.0, 'supply_fan_speed': 0.54, 'remaining_mins': 0, 'post_heat': 0.865, 'pre_heat': None, 'supply_flow': None, 'exhaust_flow': None, '_extra': '40'}
|
|
306
|
+
2026-01-15 12:54:19.538000 ... I --- 32:137185 --:------ 32:137185 31DA 030 00EF007FFFEFEF070A0786074B0600F00200035C6C0000ADEF7FFF7FFF40 # {'hvac_id': '00', 'exhaust_fan_speed': 0.46, 'fan_info': 'speed 3, high', '_unknown_fan_info_flags': [0, 0, 0], 'air_quality': None, 'co2_level': None, 'indoor_humidity': None, 'outdoor_humidity': None, 'exhaust_temp': 18.02, 'supply_temp': 19.26, 'indoor_temp': 18.67, 'outdoor_temp': 15.36, 'speed_capabilities': ['off', 'low_med_high', 'timer', 'boost', 'post_heater'], 'bypass_position': 0.0, 'supply_fan_speed': 0.54, 'remaining_mins': 0, 'post_heat': 0.865, 'pre_heat': None, 'supply_flow': None, 'exhaust_flow': None, '_extra': '40'}
|
|
307
|
+
2026-01-15 13:03:22.232000 ... I --- 32:137185 --:------ 32:137185 31DA 030 00EF007FFFEFEF07070782074505F6F002000234400000B2EF7FFF7FFF40 # {'hvac_id': '00', 'exhaust_fan_speed': 0.26, 'fan_info': 'speed 2, medium', '_unknown_fan_info_flags': [0, 0, 0], 'air_quality': None, 'co2_level': None, 'indoor_humidity': None, 'outdoor_humidity': None, 'exhaust_temp': 17.99, 'supply_temp': 19.22, 'indoor_temp': 18.61, 'outdoor_temp': 15.26, 'speed_capabilities': ['off', 'low_med_high', 'timer', 'boost', 'post_heater'], 'bypass_position': 0.0, 'supply_fan_speed': 0.32, 'remaining_mins': 0, 'post_heat': 0.89, 'pre_heat': None, 'supply_flow': None, 'exhaust_flow': None, '_extra': '40'}
|
|
308
|
+
2026-01-15 14:07:47.235000 ... RP --- 32:137185 37:145236 --:------ 31DA 030 00EF007FFFEFEF06CA07BC079F060FF00200011628000078EF7FFF7FFF40 # {'hvac_id': '00', 'exhaust_fan_speed': 0.11, 'fan_info': 'speed 1, low', '_unknown_fan_info_flags': [0, 0, 0], 'air_quality': None, 'co2_level': None, 'indoor_humidity': None, 'outdoor_humidity': None, 'exhaust_temp': 17.38, 'supply_temp': 19.8, 'indoor_temp': 19.51, 'outdoor_temp': 15.51, 'speed_capabilities': ['off', 'low_med_high', 'timer', 'boost', 'post_heater'], 'bypass_position': 0.0, 'supply_fan_speed': 0.2, 'remaining_mins': 0, 'post_heat': 0.6, 'pre_heat': None, 'supply_flow': None, 'exhaust_flow': None, '_extra': '40'}
|
|
309
|
+
2026-01-15 13:54:07.538000 ... I --- 32:137185 --:------ 32:137185 31DA 030 00EF007FFFEFEF06AE0796077E0603F0020001162800009EEF7FFF7FFF40 # {'hvac_id': '00', 'exhaust_fan_speed': 0.11, 'fan_info': 'speed 1, low', '_unknown_fan_info_flags': [0, 0, 0], 'air_quality': None, 'co2_level': None, 'indoor_humidity': None, 'outdoor_humidity': None, 'exhaust_temp': 17.1, 'supply_temp': 19.42, 'indoor_temp': 19.18, 'outdoor_temp': 15.39, 'speed_capabilities': ['off', 'low_med_high', 'timer', 'boost', 'post_heater'], 'bypass_position': 0.0, 'supply_fan_speed': 0.2, 'remaining_mins': 0, 'post_heat': 0.79, 'pre_heat': None, 'supply_flow': None, 'exhaust_flow': None, '_extra': '40'}
|
|
303
310
|
|
|
304
311
|
# Vasco D60 HRU
|
|
305
312
|
# speed is actually in 31D9[4:6]
|