ramses-rf 0.52.2__tar.gz → 0.52.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.52.2 → ramses_rf-0.52.3}/.github/workflows/check-lint.yml +1 -1
- {ramses_rf-0.52.2 → ramses_rf-0.52.3}/.github/workflows/check-test.yml +1 -1
- {ramses_rf-0.52.2 → ramses_rf-0.52.3}/.github/workflows/check-type.yml +1 -1
- {ramses_rf-0.52.2 → ramses_rf-0.52.3}/.github/workflows/publish-hatch.yml +2 -2
- {ramses_rf-0.52.2 → ramses_rf-0.52.3}/PKG-INFO +1 -1
- ramses_rf-0.52.3/docs/source/binding_process_diagram.md +159 -0
- {ramses_rf-0.52.2 → ramses_rf-0.52.3}/docs/source/conf.py +2 -0
- {ramses_rf-0.52.2 → ramses_rf-0.52.3}/docs/source/index.rst +1 -0
- {ramses_rf-0.52.2 → ramses_rf-0.52.3}/docs/source/usage.md +1 -1
- {ramses_rf-0.52.2 → ramses_rf-0.52.3}/ramses_rf/binding_fsm.py +18 -4
- {ramses_rf-0.52.2 → ramses_rf-0.52.3}/ramses_rf/database.py +2 -2
- {ramses_rf-0.52.2 → ramses_rf-0.52.3}/ramses_rf/device/heat.py +3 -6
- {ramses_rf-0.52.2 → ramses_rf-0.52.3}/ramses_rf/entity_base.py +89 -35
- {ramses_rf-0.52.2 → ramses_rf-0.52.3}/ramses_rf/system/zones.py +1 -1
- {ramses_rf-0.52.2 → ramses_rf-0.52.3}/ramses_rf/version.py +1 -1
- {ramses_rf-0.52.2 → ramses_rf-0.52.3}/ramses_tx/gateway.py +3 -0
- {ramses_rf-0.52.2 → ramses_rf-0.52.3}/ramses_tx/logger.py +8 -0
- {ramses_rf-0.52.2 → ramses_rf-0.52.3}/ramses_tx/schemas.py +4 -0
- {ramses_rf-0.52.2 → ramses_rf-0.52.3}/ramses_tx/transport.py +14 -3
- {ramses_rf-0.52.2 → ramses_rf-0.52.3}/ramses_tx/version.py +1 -1
- {ramses_rf-0.52.2 → ramses_rf-0.52.3/requirements}/requirements_docs.txt +2 -0
- {ramses_rf-0.52.2 → ramses_rf-0.52.3}/tests/tests/test_systems.py +1 -4
- {ramses_rf-0.52.2 → ramses_rf-0.52.3}/tests/tests_rf/test_database.py +32 -0
- ramses_rf-0.52.3/tests/tests_rf/test_entity_base.py +228 -0
- {ramses_rf-0.52.2 → ramses_rf-0.52.3}/.github/ISSUE_TEMPLATE/bug_report.md +0 -0
- {ramses_rf-0.52.2 → ramses_rf-0.52.3}/.github/dependabot.yml +0 -0
- {ramses_rf-0.52.2 → ramses_rf-0.52.3}/.gitignore +0 -0
- {ramses_rf-0.52.2 → ramses_rf-0.52.3}/.pre-commit-config.yaml +0 -0
- {ramses_rf-0.52.2 → ramses_rf-0.52.3}/LICENSE +0 -0
- {ramses_rf-0.52.2 → ramses_rf-0.52.3}/README-developers.md +0 -0
- {ramses_rf-0.52.2 → ramses_rf-0.52.3}/README.md +0 -0
- {ramses_rf-0.52.2 → ramses_rf-0.52.3}/client.py +0 -0
- {ramses_rf-0.52.2 → ramses_rf-0.52.3}/docs/Makefile +0 -0
- {ramses_rf-0.52.2 → ramses_rf-0.52.3}/docs/make.bat +0 -0
- {ramses_rf-0.52.2 → ramses_rf-0.52.3}/docs/source/_static/ramses_rf_logo.png +0 -0
- {ramses_rf-0.52.2 → ramses_rf-0.52.3}/docs/source/glossary.rst +0 -0
- {ramses_rf-0.52.2 → ramses_rf-0.52.3}/docs/source/modules.rst +0 -0
- {ramses_rf-0.52.2 → ramses_rf-0.52.3}/docs/source/ramses_cli.rst +0 -0
- {ramses_rf-0.52.2 → ramses_rf-0.52.3}/docs/source/ramses_rf.device.rst +0 -0
- {ramses_rf-0.52.2 → ramses_rf-0.52.3}/docs/source/ramses_rf.rst +0 -0
- {ramses_rf-0.52.2 → ramses_rf-0.52.3}/docs/source/ramses_rf.system.rst +0 -0
- {ramses_rf-0.52.2 → ramses_rf-0.52.3}/docs/source/ramses_tx.rst +0 -0
- {ramses_rf-0.52.2 → ramses_rf-0.52.3}/misc/2411_parser.py +0 -0
- {ramses_rf-0.52.2 → ramses_rf-0.52.3}/misc/fingerprints.log +0 -0
- {ramses_rf-0.52.2 → ramses_rf-0.52.3}/misc/ser2net.yaml +0 -0
- {ramses_rf-0.52.2 → ramses_rf-0.52.3}/misc/ti_3410/notes.sh +0 -0
- {ramses_rf-0.52.2 → ramses_rf-0.52.3}/misc/ti_3410/ti_3410.fw +0 -0
- {ramses_rf-0.52.2 → ramses_rf-0.52.3}/pyproject.toml +0 -0
- {ramses_rf-0.52.2 → ramses_rf-0.52.3}/ramses_cli/__init__.py +0 -0
- {ramses_rf-0.52.2 → ramses_rf-0.52.3}/ramses_cli/client.py +0 -0
- {ramses_rf-0.52.2 → ramses_rf-0.52.3}/ramses_cli/debug.py +0 -0
- {ramses_rf-0.52.2 → ramses_rf-0.52.3}/ramses_cli/discovery.py +0 -0
- {ramses_rf-0.52.2 → ramses_rf-0.52.3}/ramses_cli/utils/cat_slow.py +0 -0
- {ramses_rf-0.52.2 → ramses_rf-0.52.3}/ramses_cli/utils/convert.py +0 -0
- {ramses_rf-0.52.2 → ramses_rf-0.52.3}/ramses_rf/__init__.py +0 -0
- {ramses_rf-0.52.2 → ramses_rf-0.52.3}/ramses_rf/const.py +0 -0
- {ramses_rf-0.52.2 → ramses_rf-0.52.3}/ramses_rf/device/__init__.py +0 -0
- {ramses_rf-0.52.2 → ramses_rf-0.52.3}/ramses_rf/device/base.py +0 -0
- {ramses_rf-0.52.2 → ramses_rf-0.52.3}/ramses_rf/device/hvac.py +0 -0
- {ramses_rf-0.52.2 → ramses_rf-0.52.3}/ramses_rf/dispatcher.py +0 -0
- {ramses_rf-0.52.2 → ramses_rf-0.52.3}/ramses_rf/exceptions.py +0 -0
- {ramses_rf-0.52.2 → ramses_rf-0.52.3}/ramses_rf/gateway.py +0 -0
- {ramses_rf-0.52.2 → ramses_rf-0.52.3}/ramses_rf/helpers.py +0 -0
- {ramses_rf-0.52.2 → ramses_rf-0.52.3}/ramses_rf/py.typed +0 -0
- {ramses_rf-0.52.2 → ramses_rf-0.52.3}/ramses_rf/schemas.py +0 -0
- {ramses_rf-0.52.2 → ramses_rf-0.52.3}/ramses_rf/system/__init__.py +0 -0
- {ramses_rf-0.52.2 → ramses_rf-0.52.3}/ramses_rf/system/faultlog.py +0 -0
- {ramses_rf-0.52.2 → ramses_rf-0.52.3}/ramses_rf/system/heat.py +0 -0
- {ramses_rf-0.52.2 → ramses_rf-0.52.3}/ramses_rf/system/schedule.py +0 -0
- {ramses_rf-0.52.2 → ramses_rf-0.52.3}/ramses_tx/__init__.py +0 -0
- {ramses_rf-0.52.2 → ramses_rf-0.52.3}/ramses_tx/address.py +0 -0
- {ramses_rf-0.52.2 → ramses_rf-0.52.3}/ramses_tx/command.py +0 -0
- {ramses_rf-0.52.2 → ramses_rf-0.52.3}/ramses_tx/const.py +0 -0
- {ramses_rf-0.52.2 → ramses_rf-0.52.3}/ramses_tx/exceptions.py +0 -0
- {ramses_rf-0.52.2 → ramses_rf-0.52.3}/ramses_tx/fingerprints.py +0 -0
- {ramses_rf-0.52.2 → ramses_rf-0.52.3}/ramses_tx/frame.py +0 -0
- {ramses_rf-0.52.2 → ramses_rf-0.52.3}/ramses_tx/helpers.py +0 -0
- {ramses_rf-0.52.2 → ramses_rf-0.52.3}/ramses_tx/message.py +0 -0
- {ramses_rf-0.52.2 → ramses_rf-0.52.3}/ramses_tx/opentherm.py +0 -0
- {ramses_rf-0.52.2 → ramses_rf-0.52.3}/ramses_tx/packet.py +0 -0
- {ramses_rf-0.52.2 → ramses_rf-0.52.3}/ramses_tx/parsers.py +0 -0
- {ramses_rf-0.52.2 → ramses_rf-0.52.3}/ramses_tx/protocol.py +0 -0
- {ramses_rf-0.52.2 → ramses_rf-0.52.3}/ramses_tx/protocol_fsm.py +0 -0
- {ramses_rf-0.52.2 → ramses_rf-0.52.3}/ramses_tx/py.typed +0 -0
- {ramses_rf-0.52.2 → ramses_rf-0.52.3}/ramses_tx/ramses.py +0 -0
- {ramses_rf-0.52.2 → ramses_rf-0.52.3}/ramses_tx/typed_dicts.py +0 -0
- {ramses_rf-0.52.2 → ramses_rf-0.52.3}/ramses_tx/typing.py +0 -0
- {ramses_rf-0.52.2 → ramses_rf-0.52.3/requirements}/requirements.txt +0 -0
- {ramses_rf-0.52.2 → ramses_rf-0.52.3/requirements}/requirements_dev.txt +0 -0
- {ramses_rf-0.52.2 → ramses_rf-0.52.3}/tests/deprecated/_test_apis_mock.py +0 -0
- {ramses_rf-0.52.2 → ramses_rf-0.52.3}/tests/deprecated/_test_mock_faultlog.py +0 -0
- {ramses_rf-0.52.2 → ramses_rf-0.52.3}/tests/deprecated/_test_mock_schedule.py +0 -0
- {ramses_rf-0.52.2 → ramses_rf-0.52.3}/tests/deprecated/_test_packets_bad.py +0 -0
- {ramses_rf-0.52.2 → ramses_rf-0.52.3}/tests/deprecated/_test_performance_WIP.py +0 -0
- {ramses_rf-0.52.2 → ramses_rf-0.52.3}/tests/deprecated/_test_state_mgt.py +0 -0
- {ramses_rf-0.52.2 → ramses_rf-0.52.3}/tests/deprecated/common.py +0 -0
- {ramses_rf-0.52.2 → ramses_rf-0.52.3}/tests/deprecated/mocked_devices/__init__.py +0 -0
- {ramses_rf-0.52.2 → ramses_rf-0.52.3}/tests/deprecated/mocked_devices/command.py +0 -0
- {ramses_rf-0.52.2 → ramses_rf-0.52.3}/tests/deprecated/mocked_devices/const.py +0 -0
- {ramses_rf-0.52.2 → ramses_rf-0.52.3}/tests/deprecated/mocked_devices/device_heat.py +0 -0
- {ramses_rf-0.52.2 → ramses_rf-0.52.3}/tests/deprecated/mocked_devices/device_hvac.py +0 -0
- {ramses_rf-0.52.2 → ramses_rf-0.52.3}/tests/deprecated/mocked_devices/transport.py +0 -0
- {ramses_rf-0.52.2 → ramses_rf-0.52.3}/tests/tests/__init__.py +0 -0
- {ramses_rf-0.52.2 → ramses_rf-0.52.3}/tests/tests/bindings/heat/ctl_bdr_91t.log +0 -0
- {ramses_rf-0.52.2 → ramses_rf-0.52.3}/tests/tests/bindings/heat/dts_ctl_sensor.log +0 -0
- {ramses_rf-0.52.2 → ramses_rf-0.52.3}/tests/tests/bindings/heat/hcw_ctl_sensor.log +0 -0
- {ramses_rf-0.52.2 → ramses_rf-0.52.3}/tests/tests/bindings/heat/rnd_ctl_sensor.log +0 -0
- {ramses_rf-0.52.2 → ramses_rf-0.52.3}/tests/tests/bindings/heat/rnd_ctl_sensor.yaml +0 -0
- {ramses_rf-0.52.2 → ramses_rf-0.52.3}/tests/tests/bindings/heat/trv_ctl.log +0 -0
- {ramses_rf-0.52.2 → ramses_rf-0.52.3}/tests/tests/bindings/hvac/co2_fan_itho.json +0 -0
- {ramses_rf-0.52.2 → ramses_rf-0.52.3}/tests/tests/bindings/hvac/co2_fan_itho.log +0 -0
- {ramses_rf-0.52.2 → ramses_rf-0.52.3}/tests/tests/bindings/hvac/co2_fan_itho.yaml +0 -0
- {ramses_rf-0.52.2 → ramses_rf-0.52.3}/tests/tests/bindings/hvac/dis_fan_orcon.json +0 -0
- {ramses_rf-0.52.2 → ramses_rf-0.52.3}/tests/tests/bindings/hvac/dis_fan_orcon.log +0 -0
- {ramses_rf-0.52.2 → ramses_rf-0.52.3}/tests/tests/bindings/hvac/rem_fan_climarad.log +0 -0
- {ramses_rf-0.52.2 → ramses_rf-0.52.3}/tests/tests/bindings/hvac/rem_fan_nuaire.json +0 -0
- {ramses_rf-0.52.2 → ramses_rf-0.52.3}/tests/tests/bindings/hvac/rem_fan_nuaire.log +0 -0
- {ramses_rf-0.52.2 → ramses_rf-0.52.3}/tests/tests/bindings/hvac/rem_fan_nuaire.yaml +0 -0
- {ramses_rf-0.52.2 → ramses_rf-0.52.3}/tests/tests/bindings/hvac/rem_fan_vasco.log +0 -0
- {ramses_rf-0.52.2 → ramses_rf-0.52.3}/tests/tests/bindings/hvac/rem_fan_ventura.log +0 -0
- {ramses_rf-0.52.2 → ramses_rf-0.52.3}/tests/tests/devices/device_02.log +0 -0
- {ramses_rf-0.52.2 → ramses_rf-0.52.3}/tests/tests/devices/device_04.log +0 -0
- {ramses_rf-0.52.2 → ramses_rf-0.52.3}/tests/tests/devices/device_10.log +0 -0
- {ramses_rf-0.52.2 → ramses_rf-0.52.3}/tests/tests/devices/device_13.log +0 -0
- {ramses_rf-0.52.2 → ramses_rf-0.52.3}/tests/tests/devices/device_22.log +0 -0
- {ramses_rf-0.52.2 → ramses_rf-0.52.3}/tests/tests/eavesdrop_dev_class/hvac/known_list_eavesdrop_off.json +0 -0
- {ramses_rf-0.52.2 → ramses_rf-0.52.3}/tests/tests/eavesdrop_dev_class/hvac/known_list_eavesdrop_on.json +0 -0
- {ramses_rf-0.52.2 → ramses_rf-0.52.3}/tests/tests/eavesdrop_dev_class/hvac/packet.log +0 -0
- {ramses_rf-0.52.2 → ramses_rf-0.52.3}/tests/tests/eavesdrop_schema/_trv_actuator_long/packet.log +0 -0
- {ramses_rf-0.52.2 → ramses_rf-0.52.3}/tests/tests/eavesdrop_schema/_trv_actuator_long/schema_eavesdrop_off.json +0 -0
- {ramses_rf-0.52.2 → ramses_rf-0.52.3}/tests/tests/eavesdrop_schema/_trv_actuator_long/schema_eavesdrop_on.json +0 -0
- {ramses_rf-0.52.2 → ramses_rf-0.52.3}/tests/tests/eavesdrop_schema/_trv_actuator_mixed/packet.log +0 -0
- {ramses_rf-0.52.2 → ramses_rf-0.52.3}/tests/tests/eavesdrop_schema/_trv_actuator_mixed/schema_eavesdrop_off.json +0 -0
- {ramses_rf-0.52.2 → ramses_rf-0.52.3}/tests/tests/eavesdrop_schema/_trv_actuator_mixed/schema_eavesdrop_on.json +0 -0
- {ramses_rf-0.52.2 → ramses_rf-0.52.3}/tests/tests/eavesdrop_schema/_ufh_circuits/packet.log +0 -0
- {ramses_rf-0.52.2 → ramses_rf-0.52.3}/tests/tests/eavesdrop_schema/_ufh_circuits/schema_eavesdrop_off.json +0 -0
- {ramses_rf-0.52.2 → ramses_rf-0.52.3}/tests/tests/eavesdrop_schema/_ufh_circuits/schema_eavesdrop_on.json +0 -0
- {ramses_rf-0.52.2 → ramses_rf-0.52.3}/tests/tests/eavesdrop_schema/app_cntrl/packet.log +0 -0
- {ramses_rf-0.52.2 → ramses_rf-0.52.3}/tests/tests/eavesdrop_schema/app_cntrl/schema_eavesdrop_off.json +0 -0
- {ramses_rf-0.52.2 → ramses_rf-0.52.3}/tests/tests/eavesdrop_schema/app_cntrl/schema_eavesdrop_on.json +0 -0
- {ramses_rf-0.52.2 → ramses_rf-0.52.3}/tests/tests/eavesdrop_schema/trv_actuators/packet.log +0 -0
- {ramses_rf-0.52.2 → ramses_rf-0.52.3}/tests/tests/eavesdrop_schema/trv_actuators/schema_eavesdrop_off.json +0 -0
- {ramses_rf-0.52.2 → ramses_rf-0.52.3}/tests/tests/eavesdrop_schema/trv_actuators/schema_eavesdrop_on.json +0 -0
- {ramses_rf-0.52.2 → ramses_rf-0.52.3}/tests/tests/eavesdrop_schema/zone_sensors_000/packet.log +0 -0
- {ramses_rf-0.52.2 → ramses_rf-0.52.3}/tests/tests/eavesdrop_schema/zone_sensors_000/schema_eavesdrop_off.json +0 -0
- {ramses_rf-0.52.2 → ramses_rf-0.52.3}/tests/tests/eavesdrop_schema/zone_sensors_000/schema_eavesdrop_on.json +0 -0
- {ramses_rf-0.52.2 → ramses_rf-0.52.3}/tests/tests/eavesdrop_schema/zone_sensors_001/packet.log +0 -0
- {ramses_rf-0.52.2 → ramses_rf-0.52.3}/tests/tests/eavesdrop_schema/zone_sensors_001/schema_eavesdrop_off.json +0 -0
- {ramses_rf-0.52.2 → ramses_rf-0.52.3}/tests/tests/eavesdrop_schema/zone_sensors_001/schema_eavesdrop_on.json +0 -0
- {ramses_rf-0.52.2 → ramses_rf-0.52.3}/tests/tests/eavesdrop_schema/zone_sensors_002/packet.log +0 -0
- {ramses_rf-0.52.2 → ramses_rf-0.52.3}/tests/tests/eavesdrop_schema/zone_sensors_002/schema_eavesdrop_off.json +0 -0
- {ramses_rf-0.52.2 → ramses_rf-0.52.3}/tests/tests/eavesdrop_schema/zone_sensors_002/schema_eavesdrop_on.json +0 -0
- {ramses_rf-0.52.2 → ramses_rf-0.52.3}/tests/tests/eavesdrop_schema/zone_sensors_003/packet.log +0 -0
- {ramses_rf-0.52.2 → ramses_rf-0.52.3}/tests/tests/eavesdrop_schema/zone_sensors_003/schema_eavesdrop_off.json +0 -0
- {ramses_rf-0.52.2 → ramses_rf-0.52.3}/tests/tests/eavesdrop_schema/zone_sensors_003/schema_eavesdrop_on.json +0 -0
- {ramses_rf-0.52.2 → ramses_rf-0.52.3}/tests/tests/eavesdrop_schema/zone_sensors_004/packet.log +0 -0
- {ramses_rf-0.52.2 → ramses_rf-0.52.3}/tests/tests/eavesdrop_schema/zone_sensors_004/schema_eavesdrop_off.json +0 -0
- {ramses_rf-0.52.2 → ramses_rf-0.52.3}/tests/tests/eavesdrop_schema/zone_sensors_004/schema_eavesdrop_on.json +0 -0
- {ramses_rf-0.52.2 → ramses_rf-0.52.3}/tests/tests/fingerprints/10e0_xxxx.log +0 -0
- {ramses_rf-0.52.2 → ramses_rf-0.52.3}/tests/tests/fingerprints/_gather.sh +0 -0
- {ramses_rf-0.52.2 → ramses_rf-0.52.3}/tests/tests/fingerprints/heat/01_EvoTouch_Colour.log +0 -0
- {ramses_rf-0.52.2 → ramses_rf-0.52.3}/tests/tests/fingerprints/heat/01_Evo_Color.log +0 -0
- {ramses_rf-0.52.2 → ramses_rf-0.52.3}/tests/tests/fingerprints/heat/01_IONA_RAI_Prototype.log +0 -0
- {ramses_rf-0.52.2 → ramses_rf-0.52.3}/tests/tests/fingerprints/heat/02_HCE80_V3.10_061117..log +0 -0
- {ramses_rf-0.52.2 → ramses_rf-0.52.3}/tests/tests/fingerprints/heat/04_HR92 Radiator Ctrl_.log +0 -0
- {ramses_rf-0.52.2 → ramses_rf-0.52.3}/tests/tests/fingerprints/heat/08_Jasper_EIM.log +0 -0
- {ramses_rf-0.52.2 → ramses_rf-0.52.3}/tests/tests/fingerprints/heat/10_R8810A_Bridge.log +0 -0
- {ramses_rf-0.52.2 → ramses_rf-0.52.3}/tests/tests/fingerprints/heat/10_R8820.log +0 -0
- {ramses_rf-0.52.2 → ramses_rf-0.52.3}/tests/tests/fingerprints/heat/30_Internet_Gateway.log +0 -0
- {ramses_rf-0.52.2 → ramses_rf-0.52.3}/tests/tests/fingerprints/heat/31_Jasper_Stat_TXXX.log +0 -0
- {ramses_rf-0.52.2 → ramses_rf-0.52.3}/tests/tests/fingerprints/heat/34_T87RF2025.log +0 -0
- {ramses_rf-0.52.2 → ramses_rf-0.52.3}/tests/tests/fingerprints/hvac/18_BRDG-02A55.log +0 -0
- {ramses_rf-0.52.2 → ramses_rf-0.52.3}/tests/tests/fingerprints/hvac/18_HRA82.log +0 -0
- {ramses_rf-0.52.2 → ramses_rf-0.52.3}/tests/tests/fingerprints/hvac/20.log +0 -0
- {ramses_rf-0.52.2 → ramses_rf-0.52.3}/tests/tests/fingerprints/hvac/21_CCU-12T20.log +0 -0
- {ramses_rf-0.52.2 → ramses_rf-0.52.3}/tests/tests/fingerprints/hvac/29_VMC-07RP01.log +0 -0
- {ramses_rf-0.52.2 → ramses_rf-0.52.3}/tests/tests/fingerprints/hvac/29_VMC-15RP01.log +0 -0
- {ramses_rf-0.52.2 → ramses_rf-0.52.3}/tests/tests/fingerprints/hvac/29_VMC-17RP01.log +0 -0
- {ramses_rf-0.52.2 → ramses_rf-0.52.3}/tests/tests/fingerprints/hvac/29_VMN-07LM01.log +0 -0
- {ramses_rf-0.52.2 → ramses_rf-0.52.3}/tests/tests/fingerprints/hvac/29_VMN-15LF01.log +0 -0
- {ramses_rf-0.52.2 → ramses_rf-0.52.3}/tests/tests/fingerprints/hvac/29_VMN-17LMP01.log +0 -0
- {ramses_rf-0.52.2 → ramses_rf-0.52.3}/tests/tests/fingerprints/hvac/29_VMS-15C16.log +0 -0
- {ramses_rf-0.52.2 → ramses_rf-0.52.3}/tests/tests/fingerprints/hvac/29_VMS-17HB01.log +0 -0
- {ramses_rf-0.52.2 → ramses_rf-0.52.3}/tests/tests/fingerprints/hvac/30_BRDG-02EM23.log +0 -0
- {ramses_rf-0.52.2 → ramses_rf-0.52.3}/tests/tests/fingerprints/hvac/30_BRDG-02JAS01.log +0 -0
- {ramses_rf-0.52.2 → ramses_rf-0.52.3}/tests/tests/fingerprints/hvac/32_VMC-15RPS34.log +0 -0
- {ramses_rf-0.52.2 → ramses_rf-0.52.3}/tests/tests/fingerprints/hvac/32_VMD-15RMS64.log +0 -0
- {ramses_rf-0.52.2 → ramses_rf-0.52.3}/tests/tests/fingerprints/hvac/32_VMD-15RMS86.log +0 -0
- {ramses_rf-0.52.2 → ramses_rf-0.52.3}/tests/tests/fingerprints/hvac/32_VMD-17RPS01.log +0 -0
- {ramses_rf-0.52.2 → ramses_rf-0.52.3}/tests/tests/fingerprints/hvac/32_VMN-23LM33.log +0 -0
- {ramses_rf-0.52.2 → ramses_rf-0.52.3}/tests/tests/fingerprints/hvac/32_VMN-23LMH23.log +0 -0
- {ramses_rf-0.52.2 → ramses_rf-0.52.3}/tests/tests/fingerprints/hvac/32_VMS-15CM17.log +0 -0
- {ramses_rf-0.52.2 → ramses_rf-0.52.3}/tests/tests/fingerprints/hvac/32_VMS-23C33.log +0 -0
- {ramses_rf-0.52.2 → ramses_rf-0.52.3}/tests/tests/fingerprints/hvac/32_VMS-23HB33.log +0 -0
- {ramses_rf-0.52.2 → ramses_rf-0.52.3}/tests/tests/fingerprints/hvac/32_VMZ-15V13.log +0 -0
- {ramses_rf-0.52.2 → ramses_rf-0.52.3}/tests/tests/fingerprints/hvac/37_VMD-07RPS13.log +0 -0
- {ramses_rf-0.52.2 → ramses_rf-0.52.3}/tests/tests/fingerprints/hvac/37_VMI-15MC01log +0 -0
- {ramses_rf-0.52.2 → ramses_rf-0.52.3}/tests/tests/fingerprints/hvac/37_VMI-15WSJ53.log +0 -0
- {ramses_rf-0.52.2 → ramses_rf-0.52.3}/tests/tests/fingerprints/hvac/37_VMS-02J52.log +0 -0
- {ramses_rf-0.52.2 → ramses_rf-0.52.3}/tests/tests/fingerprints/hvac/37_VMS-12C39.log +0 -0
- {ramses_rf-0.52.2 → ramses_rf-0.52.3}/tests/tests/fingerprints/hvac/99_CVE-RF.log +0 -0
- {ramses_rf-0.52.2 → ramses_rf-0.52.3}/tests/tests/fingerprints/hvac/99_VMS-17C01.log +0 -0
- {ramses_rf-0.52.2 → ramses_rf-0.52.3}/tests/tests/helpers.py +0 -0
- {ramses_rf-0.52.2 → ramses_rf-0.52.3}/tests/tests/logger/packet_in.log +0 -0
- {ramses_rf-0.52.2 → ramses_rf-0.52.3}/tests/tests/logger/packet_out.log +0 -0
- {ramses_rf-0.52.2 → ramses_rf-0.52.3}/tests/tests/logs/pkts_bad_000.log +0 -0
- {ramses_rf-0.52.2 → ramses_rf-0.52.3}/tests/tests/logs/pkts_tba_000.log +0 -0
- {ramses_rf-0.52.2 → ramses_rf-0.52.3}/tests/tests/logs/system_cache.json +0 -0
- {ramses_rf-0.52.2 → ramses_rf-0.52.3}/tests/tests/parser_helpers/pkt_addr_set.log +0 -0
- {ramses_rf-0.52.2 → ramses_rf-0.52.3}/tests/tests/parser_helpers/pkt_dev_class.log +0 -0
- {ramses_rf-0.52.2 → ramses_rf-0.52.3}/tests/tests/parsers/code_0001_wip.log +0 -0
- {ramses_rf-0.52.2 → ramses_rf-0.52.3}/tests/tests/parsers/code_0002.log +0 -0
- {ramses_rf-0.52.2 → ramses_rf-0.52.3}/tests/tests/parsers/code_0004_wip.log +0 -0
- {ramses_rf-0.52.2 → ramses_rf-0.52.3}/tests/tests/parsers/code_0005.log +0 -0
- {ramses_rf-0.52.2 → ramses_rf-0.52.3}/tests/tests/parsers/code_0006.log +0 -0
- {ramses_rf-0.52.2 → ramses_rf-0.52.3}/tests/tests/parsers/code_0008.log +0 -0
- {ramses_rf-0.52.2 → ramses_rf-0.52.3}/tests/tests/parsers/code_0009.log +0 -0
- {ramses_rf-0.52.2 → ramses_rf-0.52.3}/tests/tests/parsers/code_000a.log +0 -0
- {ramses_rf-0.52.2 → ramses_rf-0.52.3}/tests/tests/parsers/code_000c.log +0 -0
- {ramses_rf-0.52.2 → ramses_rf-0.52.3}/tests/tests/parsers/code_000e.log +0 -0
- {ramses_rf-0.52.2 → ramses_rf-0.52.3}/tests/tests/parsers/code_01ff_wip.log +0 -0
- {ramses_rf-0.52.2 → ramses_rf-0.52.3}/tests/tests/parsers/code_0418.log +0 -0
- {ramses_rf-0.52.2 → ramses_rf-0.52.3}/tests/tests/parsers/code_042f.log +0 -0
- {ramses_rf-0.52.2 → ramses_rf-0.52.3}/tests/tests/parsers/code_1030.log +0 -0
- {ramses_rf-0.52.2 → ramses_rf-0.52.3}/tests/tests/parsers/code_1060.log +0 -0
- {ramses_rf-0.52.2 → ramses_rf-0.52.3}/tests/tests/parsers/code_10d0.log +0 -0
- {ramses_rf-0.52.2 → ramses_rf-0.52.3}/tests/tests/parsers/code_10e0.log +0 -0
- {ramses_rf-0.52.2 → ramses_rf-0.52.3}/tests/tests/parsers/code_1260.log +0 -0
- {ramses_rf-0.52.2 → ramses_rf-0.52.3}/tests/tests/parsers/code_1298.log +0 -0
- {ramses_rf-0.52.2 → ramses_rf-0.52.3}/tests/tests/parsers/code_12a0.log +0 -0
- {ramses_rf-0.52.2 → ramses_rf-0.52.3}/tests/tests/parsers/code_12c0.log +0 -0
- {ramses_rf-0.52.2 → ramses_rf-0.52.3}/tests/tests/parsers/code_1300.log +0 -0
- {ramses_rf-0.52.2 → ramses_rf-0.52.3}/tests/tests/parsers/code_1f09.log +0 -0
- {ramses_rf-0.52.2 → ramses_rf-0.52.3}/tests/tests/parsers/code_1fc9.log +0 -0
- {ramses_rf-0.52.2 → ramses_rf-0.52.3}/tests/tests/parsers/code_1fd4.log +0 -0
- {ramses_rf-0.52.2 → ramses_rf-0.52.3}/tests/tests/parsers/code_2210.log +0 -0
- {ramses_rf-0.52.2 → ramses_rf-0.52.3}/tests/tests/parsers/code_22c9.log +0 -0
- {ramses_rf-0.52.2 → ramses_rf-0.52.3}/tests/tests/parsers/code_22d0.log +0 -0
- {ramses_rf-0.52.2 → ramses_rf-0.52.3}/tests/tests/parsers/code_22d9.log +0 -0
- {ramses_rf-0.52.2 → ramses_rf-0.52.3}/tests/tests/parsers/code_22e0.log +0 -0
- {ramses_rf-0.52.2 → ramses_rf-0.52.3}/tests/tests/parsers/code_22e5.log +0 -0
- {ramses_rf-0.52.2 → ramses_rf-0.52.3}/tests/tests/parsers/code_22e9.log +0 -0
- {ramses_rf-0.52.2 → ramses_rf-0.52.3}/tests/tests/parsers/code_22f1.log +0 -0
- {ramses_rf-0.52.2 → ramses_rf-0.52.3}/tests/tests/parsers/code_22f2.log +0 -0
- {ramses_rf-0.52.2 → ramses_rf-0.52.3}/tests/tests/parsers/code_22f3.log +0 -0
- {ramses_rf-0.52.2 → ramses_rf-0.52.3}/tests/tests/parsers/code_22f4.log +0 -0
- {ramses_rf-0.52.2 → ramses_rf-0.52.3}/tests/tests/parsers/code_22f7.log +0 -0
- {ramses_rf-0.52.2 → ramses_rf-0.52.3}/tests/tests/parsers/code_2309.log +0 -0
- {ramses_rf-0.52.2 → ramses_rf-0.52.3}/tests/tests/parsers/code_2349.log +0 -0
- {ramses_rf-0.52.2 → ramses_rf-0.52.3}/tests/tests/parsers/code_2411_wip.log +0 -0
- {ramses_rf-0.52.2 → ramses_rf-0.52.3}/tests/tests/parsers/code_2e04.log +0 -0
- {ramses_rf-0.52.2 → ramses_rf-0.52.3}/tests/tests/parsers/code_2e10_wip.log +0 -0
- {ramses_rf-0.52.2 → ramses_rf-0.52.3}/tests/tests/parsers/code_30c9.log +0 -0
- {ramses_rf-0.52.2 → ramses_rf-0.52.3}/tests/tests/parsers/code_3110_wip.log +0 -0
- {ramses_rf-0.52.2 → ramses_rf-0.52.3}/tests/tests/parsers/code_3120.log +0 -0
- {ramses_rf-0.52.2 → ramses_rf-0.52.3}/tests/tests/parsers/code_313e_wip.log +0 -0
- {ramses_rf-0.52.2 → ramses_rf-0.52.3}/tests/tests/parsers/code_3150.log +0 -0
- {ramses_rf-0.52.2 → ramses_rf-0.52.3}/tests/tests/parsers/code_31d9.log +0 -0
- {ramses_rf-0.52.2 → ramses_rf-0.52.3}/tests/tests/parsers/code_31da.log +0 -0
- {ramses_rf-0.52.2 → ramses_rf-0.52.3}/tests/tests/parsers/code_3200.log +0 -0
- {ramses_rf-0.52.2 → ramses_rf-0.52.3}/tests/tests/parsers/code_3210.log +0 -0
- {ramses_rf-0.52.2 → ramses_rf-0.52.3}/tests/tests/parsers/code_3220.log +0 -0
- {ramses_rf-0.52.2 → ramses_rf-0.52.3}/tests/tests/parsers/code_3222.log +0 -0
- {ramses_rf-0.52.2 → ramses_rf-0.52.3}/tests/tests/parsers/code_3ef0_wip.log +0 -0
- {ramses_rf-0.52.2 → ramses_rf-0.52.3}/tests/tests/parsers/code_3ef1_wip.log +0 -0
- {ramses_rf-0.52.2 → ramses_rf-0.52.3}/tests/tests/parsers/code_4e01.log +0 -0
- {ramses_rf-0.52.2 → ramses_rf-0.52.3}/tests/tests/parsers/code_4e02.log +0 -0
- {ramses_rf-0.52.2 → ramses_rf-0.52.3}/tests/tests/parsers/code_4e04.log +0 -0
- {ramses_rf-0.52.2 → ramses_rf-0.52.3}/tests/tests/parsers/code_4e15.log +0 -0
- {ramses_rf-0.52.2 → ramses_rf-0.52.3}/tests/tests/schedules/_sched_002/packet.log +0 -0
- {ramses_rf-0.52.2 → ramses_rf-0.52.3}/tests/tests/schedules/_sched_002/schedule.json +0 -0
- {ramses_rf-0.52.2 → ramses_rf-0.52.3}/tests/tests/schedules/sched_001/packet.log +0 -0
- {ramses_rf-0.52.2 → ramses_rf-0.52.3}/tests/tests/schedules/sched_001/schedule.json +0 -0
- {ramses_rf-0.52.2 → ramses_rf-0.52.3}/tests/tests/schedules/sched_dhw/packet.log +0 -0
- {ramses_rf-0.52.2 → ramses_rf-0.52.3}/tests/tests/schedules/sched_dhw/schedule.json +0 -0
- {ramses_rf-0.52.2 → ramses_rf-0.52.3}/tests/tests/schemas/jsn_files/schema_100.json +0 -0
- {ramses_rf-0.52.2 → ramses_rf-0.52.3}/tests/tests/schemas/jsn_files/schema_101.json +0 -0
- {ramses_rf-0.52.2 → ramses_rf-0.52.3}/tests/tests/schemas/jsn_files/schema_102.json +0 -0
- {ramses_rf-0.52.2 → ramses_rf-0.52.3}/tests/tests/schemas/jsn_files/schema_103.json +0 -0
- {ramses_rf-0.52.2 → ramses_rf-0.52.3}/tests/tests/schemas/jsn_files/schema_104.json +0 -0
- {ramses_rf-0.52.2 → ramses_rf-0.52.3}/tests/tests/schemas/jsn_files/schema_105.json +0 -0
- {ramses_rf-0.52.2 → ramses_rf-0.52.3}/tests/tests/schemas/jsn_files/schema_108.json +0 -0
- {ramses_rf-0.52.2 → ramses_rf-0.52.3}/tests/tests/schemas/log_files/schema_000.json +0 -0
- {ramses_rf-0.52.2 → ramses_rf-0.52.3}/tests/tests/schemas/log_files/schema_000.log +0 -0
- {ramses_rf-0.52.2 → ramses_rf-0.52.3}/tests/tests/schemas/log_files/schema_001.json +0 -0
- {ramses_rf-0.52.2 → ramses_rf-0.52.3}/tests/tests/schemas/log_files/schema_001.log +0 -0
- {ramses_rf-0.52.2 → ramses_rf-0.52.3}/tests/tests/schemas/log_files/schema_002.json +0 -0
- {ramses_rf-0.52.2 → ramses_rf-0.52.3}/tests/tests/schemas/log_files/schema_002.log +0 -0
- {ramses_rf-0.52.2 → ramses_rf-0.52.3}/tests/tests/schemas/log_files/schema_010.json +0 -0
- {ramses_rf-0.52.2 → ramses_rf-0.52.3}/tests/tests/schemas/log_files/schema_010.log +0 -0
- {ramses_rf-0.52.2 → ramses_rf-0.52.3}/tests/tests/schemas/log_files/schema_011.json +0 -0
- {ramses_rf-0.52.2 → ramses_rf-0.52.3}/tests/tests/schemas/log_files/schema_011.log +0 -0
- {ramses_rf-0.52.2 → ramses_rf-0.52.3}/tests/tests/schemas/log_files/schema_012.json +0 -0
- {ramses_rf-0.52.2 → ramses_rf-0.52.3}/tests/tests/schemas/log_files/schema_012.log +0 -0
- {ramses_rf-0.52.2 → ramses_rf-0.52.3}/tests/tests/schemas/log_files/schema_013.json +0 -0
- {ramses_rf-0.52.2 → ramses_rf-0.52.3}/tests/tests/schemas/log_files/schema_013.log +0 -0
- {ramses_rf-0.52.2 → ramses_rf-0.52.3}/tests/tests/schemas/log_files/schema_014.json +0 -0
- {ramses_rf-0.52.2 → ramses_rf-0.52.3}/tests/tests/schemas/log_files/schema_014.log +0 -0
- {ramses_rf-0.52.2 → ramses_rf-0.52.3}/tests/tests/schemas/log_files/schema_300.json +0 -0
- {ramses_rf-0.52.2 → ramses_rf-0.52.3}/tests/tests/schemas/log_files/schema_300.log +0 -0
- {ramses_rf-0.52.2 → ramses_rf-0.52.3}/tests/tests/schemas/log_files/schema_301.json +0 -0
- {ramses_rf-0.52.2 → ramses_rf-0.52.3}/tests/tests/schemas/log_files/schema_301.log +0 -0
- {ramses_rf-0.52.2 → ramses_rf-0.52.3}/tests/tests/schemas/log_files/schema_302.json +0 -0
- {ramses_rf-0.52.2 → ramses_rf-0.52.3}/tests/tests/schemas/log_files/schema_302.log +0 -0
- {ramses_rf-0.52.2 → ramses_rf-0.52.3}/tests/tests/schemas/log_files/schema_303.json +0 -0
- {ramses_rf-0.52.2 → ramses_rf-0.52.3}/tests/tests/schemas/log_files/schema_303.log +0 -0
- {ramses_rf-0.52.2 → ramses_rf-0.52.3}/tests/tests/schemas/log_files/schema_304.json +0 -0
- {ramses_rf-0.52.2 → ramses_rf-0.52.3}/tests/tests/schemas/log_files/schema_304.log +0 -0
- {ramses_rf-0.52.2 → ramses_rf-0.52.3}/tests/tests/schemas/log_files/schema_310.json +0 -0
- {ramses_rf-0.52.2 → ramses_rf-0.52.3}/tests/tests/schemas/log_files/schema_310.log +0 -0
- {ramses_rf-0.52.2 → ramses_rf-0.52.3}/tests/tests/systems/_heat_trv_00/config.json +0 -0
- {ramses_rf-0.52.2 → ramses_rf-0.52.3}/tests/tests/systems/_heat_trv_00/packet.log +0 -0
- {ramses_rf-0.52.2 → ramses_rf-0.52.3}/tests/tests/systems/_heat_trv_00/schema.json +0 -0
- {ramses_rf-0.52.2 → ramses_rf-0.52.3}/tests/tests/systems/_hvac_nuaire/config.json +0 -0
- {ramses_rf-0.52.2 → ramses_rf-0.52.3}/tests/tests/systems/_hvac_nuaire/known_list.json +0 -0
- {ramses_rf-0.52.2 → ramses_rf-0.52.3}/tests/tests/systems/_hvac_nuaire/packet.log +0 -0
- {ramses_rf-0.52.2 → ramses_rf-0.52.3}/tests/tests/systems/_hvac_nuaire/schema.json +0 -0
- {ramses_rf-0.52.2 → ramses_rf-0.52.3}/tests/tests/systems/_hvac_nuaire/status.json +0 -0
- {ramses_rf-0.52.2 → ramses_rf-0.52.3}/tests/tests/systems/heat_otb_00/config.json +0 -0
- {ramses_rf-0.52.2 → ramses_rf-0.52.3}/tests/tests/systems/heat_otb_00/packet.log +0 -0
- {ramses_rf-0.52.2 → ramses_rf-0.52.3}/tests/tests/systems/heat_otb_00/schema.json +0 -0
- {ramses_rf-0.52.2 → ramses_rf-0.52.3}/tests/tests/systems/heat_simple/packet.log +0 -0
- {ramses_rf-0.52.2 → ramses_rf-0.52.3}/tests/tests/systems/heat_simple/schema.json +0 -0
- {ramses_rf-0.52.2 → ramses_rf-0.52.3}/tests/tests/systems/heat_ufc_00/config.json +0 -0
- {ramses_rf-0.52.2 → ramses_rf-0.52.3}/tests/tests/systems/heat_ufc_00/packet.log +0 -0
- {ramses_rf-0.52.2 → ramses_rf-0.52.3}/tests/tests/systems/heat_ufc_01/packet.log +0 -0
- {ramses_rf-0.52.2 → ramses_rf-0.52.3}/tests/tests/systems/heat_zxdavb/config.json +0 -0
- {ramses_rf-0.52.2 → ramses_rf-0.52.3}/tests/tests/systems/heat_zxdavb/known_list.json +0 -0
- {ramses_rf-0.52.2 → ramses_rf-0.52.3}/tests/tests/systems/heat_zxdavb/packet.log +0 -0
- {ramses_rf-0.52.2 → ramses_rf-0.52.3}/tests/tests/systems/heat_zxdavb/schema.json +0 -0
- {ramses_rf-0.52.2 → ramses_rf-0.52.3}/tests/tests/test_api_faultlog.py +0 -0
- {ramses_rf-0.52.2 → ramses_rf-0.52.3}/tests/tests/test_api_schedule.py +0 -0
- {ramses_rf-0.52.2 → ramses_rf-0.52.3}/tests/tests/test_apis_binding.py +0 -0
- {ramses_rf-0.52.2 → ramses_rf-0.52.3}/tests/tests/test_apis_common.py +0 -0
- {ramses_rf-0.52.2 → ramses_rf-0.52.3}/tests/tests/test_apis_heat.py +0 -0
- {ramses_rf-0.52.2 → ramses_rf-0.52.3}/tests/tests/test_apis_hvac.py +0 -0
- {ramses_rf-0.52.2 → ramses_rf-0.52.3}/tests/tests/test_cli_utility.py +0 -0
- {ramses_rf-0.52.2 → ramses_rf-0.52.3}/tests/tests/test_devices.py +0 -0
- {ramses_rf-0.52.2 → ramses_rf-0.52.3}/tests/tests/test_eavesdrop_dev_class.py +0 -0
- {ramses_rf-0.52.2 → ramses_rf-0.52.3}/tests/tests/test_eavesdrop_schema.py +0 -0
- {ramses_rf-0.52.2 → ramses_rf-0.52.3}/tests/tests/test_helpers.py +0 -0
- {ramses_rf-0.52.2 → ramses_rf-0.52.3}/tests/tests/test_parser_helpers.py +0 -0
- {ramses_rf-0.52.2 → ramses_rf-0.52.3}/tests/tests/test_parsers.py +0 -0
- {ramses_rf-0.52.2 → ramses_rf-0.52.3}/tests/tests/test_ramses_schema.py +0 -0
- {ramses_rf-0.52.2 → ramses_rf-0.52.3}/tests/tests/test_schema_bits.py +0 -0
- {ramses_rf-0.52.2 → ramses_rf-0.52.3}/tests/tests/test_schemas.py +0 -0
- {ramses_rf-0.52.2 → ramses_rf-0.52.3}/tests/tests/test_vol_schemas.py +0 -0
- {ramses_rf-0.52.2 → ramses_rf-0.52.3}/tests/tests_rf/__init__.py +0 -0
- {ramses_rf-0.52.2 → ramses_rf-0.52.3}/tests/tests_rf/configs/config_heat.json +0 -0
- {ramses_rf-0.52.2 → ramses_rf-0.52.3}/tests/tests_rf/configs/config_hvac.json +0 -0
- {ramses_rf-0.52.2 → ramses_rf-0.52.3}/tests/tests_rf/conftest.py +0 -0
- {ramses_rf-0.52.2 → ramses_rf-0.52.3}/tests/tests_rf/device/__init__.py +0 -0
- {ramses_rf-0.52.2 → ramses_rf-0.52.3}/tests/tests_rf/device/test_hvac_ventilator.py +0 -0
- {ramses_rf-0.52.2 → ramses_rf-0.52.3}/tests/tests_rf/logs/test_api_faultlog.log +0 -0
- {ramses_rf-0.52.2 → ramses_rf-0.52.3}/tests/tests_rf/test_api_faultlog.py +0 -0
- {ramses_rf-0.52.2 → ramses_rf-0.52.3}/tests/tests_rf/test_api_schedule.py +0 -0
- {ramses_rf-0.52.2 → ramses_rf-0.52.3}/tests/tests_rf/test_binding_fsm.py +0 -0
- {ramses_rf-0.52.2 → ramses_rf-0.52.3}/tests/tests_rf/test_create_stack.py +0 -0
- {ramses_rf-0.52.2 → ramses_rf-0.52.3}/tests/tests_rf/test_dispatcher.py +0 -0
- {ramses_rf-0.52.2 → ramses_rf-0.52.3}/tests/tests_rf/test_hgi_behaviors.py +0 -0
- {ramses_rf-0.52.2 → ramses_rf-0.52.3}/tests/tests_rf/test_protocol_fsm.py +0 -0
- {ramses_rf-0.52.2 → ramses_rf-0.52.3}/tests/tests_rf/test_use_regex.py +0 -0
- {ramses_rf-0.52.2 → ramses_rf-0.52.3}/tests/tests_rf/test_virt_network.py +0 -0
- {ramses_rf-0.52.2 → ramses_rf-0.52.3}/tests/tests_rf/virtual_rf/__init__.py +0 -0
- {ramses_rf-0.52.2 → ramses_rf-0.52.3}/tests/tests_rf/virtual_rf/const.py +0 -0
- {ramses_rf-0.52.2 → ramses_rf-0.52.3}/tests/tests_rf/virtual_rf/helpers.py +0 -0
- {ramses_rf-0.52.2 → ramses_rf-0.52.3}/tests/tests_rf/virtual_rf/virtual_rf.py +0 -0
- {ramses_rf-0.52.2 → ramses_rf-0.52.3}/tests/tests_tx/__init__.py +0 -0
- {ramses_rf-0.52.2 → ramses_rf-0.52.3}/tests/tests_tx/test_command.py +0 -0
- {ramses_rf-0.52.2 → ramses_rf-0.52.3}/tests/wip/_test_eavesdrop_dhw_sensor.py +0 -0
- {ramses_rf-0.52.2 → ramses_rf-0.52.3}/tests/wip/_test_eavesdrop_htg_control.py +0 -0
- {ramses_rf-0.52.2 → ramses_rf-0.52.3}/tests/wip/_test_eavesdrop_ufc_circuits.py +0 -0
- {ramses_rf-0.52.2 → ramses_rf-0.52.3}/tests/wip/_test_eavesdrop_zone_sensors.py +0 -0
- {ramses_rf-0.52.2 → ramses_rf-0.52.3}/tests/wip/_test_eavesdrop_zone_type.py +0 -0
- {ramses_rf-0.52.2 → ramses_rf-0.52.3}/tests/wip/test_wip_cli.sh +0 -0
|
@@ -41,7 +41,7 @@ jobs:
|
|
|
41
41
|
- name: Install dependencies
|
|
42
42
|
run: |
|
|
43
43
|
python -m pip install --upgrade pip
|
|
44
|
-
pip install ruff # pip install -r requirements_dev.txt
|
|
44
|
+
pip install ruff # pip install -r requirements/requirements_dev.txt
|
|
45
45
|
|
|
46
46
|
- name: Check with ruff
|
|
47
47
|
run: ruff check --output-format=github .
|
|
@@ -41,7 +41,7 @@ jobs:
|
|
|
41
41
|
- name: Install dependencies
|
|
42
42
|
run: |
|
|
43
43
|
python -m pip install --upgrade pip
|
|
44
|
-
pip install -r requirements_dev.txt
|
|
44
|
+
pip install -r requirements/requirements_dev.txt
|
|
45
45
|
|
|
46
46
|
- name: Install the package (its dependencies are needed for typing)
|
|
47
47
|
run: pip install -e .
|
|
@@ -26,7 +26,7 @@ jobs:
|
|
|
26
26
|
run: hatch build
|
|
27
27
|
|
|
28
28
|
- name: Upload dist
|
|
29
|
-
uses: actions/upload-artifact@
|
|
29
|
+
uses: actions/upload-artifact@v5
|
|
30
30
|
with:
|
|
31
31
|
name: dist
|
|
32
32
|
path: dist/
|
|
@@ -40,7 +40,7 @@ jobs:
|
|
|
40
40
|
url: https://pypi.org/project/ramses_rf
|
|
41
41
|
steps:
|
|
42
42
|
- name: Download dist
|
|
43
|
-
uses: actions/download-artifact@
|
|
43
|
+
uses: actions/download-artifact@v6
|
|
44
44
|
with:
|
|
45
45
|
name: dist
|
|
46
46
|
path: dist/
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: ramses_rf
|
|
3
|
-
Version: 0.52.
|
|
3
|
+
Version: 0.52.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
|
|
@@ -0,0 +1,159 @@
|
|
|
1
|
+
# RAMSES RF Binding Process Diagram
|
|
2
|
+
|
|
3
|
+
## Overview
|
|
4
|
+
This diagram shows the binding finite state machine (FSM) for RAMSES RF devices, illustrating the complete process from initial state to binding completion.
|
|
5
|
+
|
|
6
|
+
## State Machine Diagram
|
|
7
|
+
|
|
8
|
+
```mermaid
|
|
9
|
+
stateDiagram-v2
|
|
10
|
+
direction LR
|
|
11
|
+
[*] --> DevIsNotBinding
|
|
12
|
+
DevIsNotBinding --> InitiateBindingProcess : initiate_binding_process()
|
|
13
|
+
InitiateBindingProcess --> SuppSendOfferWaitForAccept
|
|
14
|
+
SuppSendOfferWaitForAccept --> OfferSent : _make_offer()
|
|
15
|
+
OfferSent --> SuppSendOfferWaitForAccept : wait_for_accept()
|
|
16
|
+
DevIsNotBinding --> RespIsWaitingForOffer : wait_for_binding_request()
|
|
17
|
+
RespIsWaitingForOffer --> OfferReceived : _wait_for_offer()
|
|
18
|
+
OfferReceived --> RespSendAcceptWaitForConfirm : _accept_offer()
|
|
19
|
+
RespSendAcceptWaitForConfirm --> SuppIsReadyToSendConfirm : wait_for_confirm()
|
|
20
|
+
SuppIsReadyToSendConfirm --> StateDecisionPoint : cast_confirm_accept()
|
|
21
|
+
StateDecisionPoint --> RespHasBoundAsRespondent : No addenda
|
|
22
|
+
StateDecisionPoint --> SuppHasBoundAsSupplicant : Yes addenda / Complete
|
|
23
|
+
RespHasBoundAsRespondent --> DevIsNotBinding
|
|
24
|
+
SuppHasBoundAsSupplicant --> DevIsNotBinding
|
|
25
|
+
DevIsNotBinding --> [*] : Binding Complete
|
|
26
|
+
|
|
27
|
+
subgraph Supplicant Role
|
|
28
|
+
SuppSendOfferWaitForAccept
|
|
29
|
+
OfferSent
|
|
30
|
+
SuppIsReadyToSendConfirm
|
|
31
|
+
SuppHasBoundAsSupplicant
|
|
32
|
+
end
|
|
33
|
+
|
|
34
|
+
subgraph Respondent Role
|
|
35
|
+
RespIsWaitingForOffer
|
|
36
|
+
OfferReceived
|
|
37
|
+
RespSendAcceptWaitForConfirm
|
|
38
|
+
RespHasBoundAsRespondent
|
|
39
|
+
end
|
|
40
|
+
|
|
41
|
+
classDef supplicant fill:#006400,stroke:#ffffff,stroke-width:2px
|
|
42
|
+
classDef respondent fill:#00008B,stroke:#ffffff,stroke-width:2px
|
|
43
|
+
|
|
44
|
+
class SuppSendOfferWaitForAccept,OfferSent,SuppIsReadyToSendConfirm,SuppHasBoundAsSupplicant supplicant
|
|
45
|
+
class RespIsWaitingForOffer,OfferReceived,RespSendAcceptWaitForConfirm,RespHasBoundAsRespondent respondent
|
|
46
|
+
class Supplicant Role supplicant
|
|
47
|
+
class Respondent Role respondent
|
|
48
|
+
|
|
49
|
+
note right of DevIsNotBinding
|
|
50
|
+
Not binding<br/>Ready to start
|
|
51
|
+
end note
|
|
52
|
+
|
|
53
|
+
note right of SuppSendOfferWaitForAccept
|
|
54
|
+
Made Offer<br/>Waiting for Accept
|
|
55
|
+
end note
|
|
56
|
+
|
|
57
|
+
note right of RespIsWaitingForOffer
|
|
58
|
+
Waiting for Offer
|
|
59
|
+
end note
|
|
60
|
+
|
|
61
|
+
note right of RespSendAcceptWaitForConfirm
|
|
62
|
+
Sent Accept<br/>Waiting for Confirm
|
|
63
|
+
end note
|
|
64
|
+
|
|
65
|
+
note right of SuppIsReadyToSendConfirm
|
|
66
|
+
Received Accept<br/>Ready to send Confirm
|
|
67
|
+
end note
|
|
68
|
+
|
|
69
|
+
note right of StateDecisionPoint
|
|
70
|
+
If addenda: SendAddenda<br/>If no addenda: Complete
|
|
71
|
+
end note
|
|
72
|
+
|
|
73
|
+
note right of RespHasBoundAsRespondent
|
|
74
|
+
Binding Complete
|
|
75
|
+
end note
|
|
76
|
+
|
|
77
|
+
note right of SuppHasBoundAsSupplicant
|
|
78
|
+
Binding Complete<br/>Nothing more to do
|
|
79
|
+
end note
|
|
80
|
+
```
|
|
81
|
+
|
|
82
|
+
## Method Flow by Role
|
|
83
|
+
|
|
84
|
+
### Supplicant Flow (Device initiating binding)
|
|
85
|
+
```python
|
|
86
|
+
async def initiate_binding_process(self, offer_codes, confirm_code=None, ratify_cmd=None):
|
|
87
|
+
1. _make_offer(offer_codes, oem_code) # Send Offer packet
|
|
88
|
+
2. _wait_for_accept(tender) # Wait for Accept response
|
|
89
|
+
3. _confirm_accept(accept, confirm_code) # Send Confirm packet
|
|
90
|
+
4. _cast_addenda(accept, ratify_cmd) # Optional: Send Addenda
|
|
91
|
+
|
|
92
|
+
# Result: SuppHasBoundAsSupplicant state
|
|
93
|
+
```
|
|
94
|
+
|
|
95
|
+
### Respondent Flow (Device responding to binding)
|
|
96
|
+
```python
|
|
97
|
+
async def wait_for_binding_request(self, accept_codes, idx="00", require_ratify=False):
|
|
98
|
+
1. _wait_for_offer() # Wait for Offer packet
|
|
99
|
+
2. _accept_offer(tender, accept_codes, idx) # Send Accept packet
|
|
100
|
+
3. _wait_for_confirm(accept) # Wait for Confirm packet
|
|
101
|
+
4. _wait_for_addenda(accept) # Optional: Wait for Addenda
|
|
102
|
+
|
|
103
|
+
# Result: RespHasBoundAsRespondent state
|
|
104
|
+
```
|
|
105
|
+
|
|
106
|
+
## State Details
|
|
107
|
+
|
|
108
|
+
| State | Role | Description | Key Methods |
|
|
109
|
+
|-------|------|-------------|-------------|
|
|
110
|
+
| `DevIsNotBinding` | Any | Initial/final state, not participating in binding | - |
|
|
111
|
+
| `RespIsWaitingForOffer` | Respondent | Waiting for binding offer from supplicant | `wait_for_offer()` |
|
|
112
|
+
| `RespSendAcceptWaitForConfirm` | Respondent | Sent Accept, waiting for Confirm | `cast_accept_offer()`, `wait_for_confirm()` |
|
|
113
|
+
| `RespIsWaitingForAddenda` | Respondent | Received Confirm, waiting for optional Addenda | `wait_for_addenda()` |
|
|
114
|
+
| `RespHasBoundAsRespondent` | Respondent | Binding completed successfully | ✅ **NEW LOGGING HERE** |
|
|
115
|
+
| `SuppSendOfferWaitForAccept` | Supplicant | Sent Offer, waiting for Accept | `cast_offer()`, `wait_for_accept()` |
|
|
116
|
+
| `SuppIsReadyToSendConfirm` | Supplicant | Received Accept, ready to send Confirm | `cast_confirm_accept()` |
|
|
117
|
+
| `SuppIsReadyToSendAddenda` | Supplicant | Sent Confirm, ready to send Addenda | `cast_addenda()` |
|
|
118
|
+
| `SuppHasBoundAsSupplicant` | Supplicant | Binding completed successfully | ✅ **NEW LOGGING HERE** |
|
|
119
|
+
| `DevHasFailedBinding` | Any | Binding failed, error state | - |
|
|
120
|
+
|
|
121
|
+
## Binding Phases (Packet Types)
|
|
122
|
+
|
|
123
|
+
| Phase | Packet Type | Description | Direction |
|
|
124
|
+
|-------|-------------|-------------|-----------|
|
|
125
|
+
| `TENDER` | `1FC9` (I_) | Offer phase - initial binding proposal | Supplicant → Respondent |
|
|
126
|
+
| `ACCEPT` | `1FC9` (W_) | Accept phase - acceptance of offer | Respondent → Supplicant |
|
|
127
|
+
| `AFFIRM` | `1FC9` (I_) | Confirm phase - confirmation of acceptance | Supplicant → Respondent |
|
|
128
|
+
| `RATIFY` | `10E0` (I_) | Addenda phase - optional additional binding info | Either direction |
|
|
129
|
+
|
|
130
|
+
## New Logging Implementation
|
|
131
|
+
|
|
132
|
+
The following log.info statements have been added at binding completion points:
|
|
133
|
+
|
|
134
|
+
### 1. Constructor Logging (Immediate Confirmation)
|
|
135
|
+
- **`RespHasBoundAsRespondent.__init__()`**: Logs when respondent binding completes
|
|
136
|
+
- **`SuppHasBoundAsSupplicant.__init__()`**: Logs when supplicant binding completes
|
|
137
|
+
|
|
138
|
+
### 2. State Transition Logging (Complete Flow)
|
|
139
|
+
- **`BindContextBase.set_state()`**: Logs the complete state transition to bound states, including:
|
|
140
|
+
- Previous state name
|
|
141
|
+
- New bound state name
|
|
142
|
+
- Final role (respondent/supplicant)
|
|
143
|
+
|
|
144
|
+
## Example Log Output
|
|
145
|
+
```
|
|
146
|
+
INFO:ramses_rf.binding_fsm:32:123456: Binding completed as respondent
|
|
147
|
+
INFO:ramses_rf.binding_fsm:37:789012: Binding completed as supplicant
|
|
148
|
+
INFO:ramses_rf.binding_fsm:32:123456: Binding process completed: RespSendAcceptWaitForConfirm -> RespHasBoundAsRespondent (role: BindRole.RESPONDENT)
|
|
149
|
+
```
|
|
150
|
+
|
|
151
|
+
## Error Handling
|
|
152
|
+
- **Timeout**: Binding fails if expected packets not received within timeout periods
|
|
153
|
+
- **Retry Limits**: Automatic failure after retry limits exceeded
|
|
154
|
+
- **Exception**: `BindingFlowFailed` raised on binding errors
|
|
155
|
+
|
|
156
|
+
## Configuration Constants
|
|
157
|
+
- `CONFIRM_RETRY_LIMIT`: 3 (automatic binding after this many confirm sends)
|
|
158
|
+
- `CONFIRM_TIMEOUT_SECS`: 3 (automatic binding after this many seconds)
|
|
159
|
+
- `WAITING_TIMEOUT_SECS`: 5 (fail if no packet received within this time)
|
|
@@ -36,6 +36,7 @@ extensions = [
|
|
|
36
36
|
"sphinx.ext.githubpages",
|
|
37
37
|
"sphinx_design",
|
|
38
38
|
"myst_parser", # to use Markdown inside reST
|
|
39
|
+
"sphinxcontrib.mermaid", # to show mermaid diagrams in docs
|
|
39
40
|
]
|
|
40
41
|
pygments_style = "sphinx" # enable syntax highlighting
|
|
41
42
|
|
|
@@ -72,3 +73,4 @@ autosummary_generate_overwrite = True
|
|
|
72
73
|
# Myst
|
|
73
74
|
myst_enable_extensions = ["colon_fence"]
|
|
74
75
|
myst_heading_anchors = 4
|
|
76
|
+
myst_fence_as_directive = ["mermaid"]
|
|
@@ -15,7 +15,7 @@ MyST [markup](https://myst-parser.readthedocs.io/en/latest/syntax/organising_con
|
|
|
15
15
|
|
|
16
16
|
- Activate your virtual environment for ramses_rf as described in the [Wiki](https://github.com/ramses-rf/ramses_rf/blob/master/README-developers.md).
|
|
17
17
|
|
|
18
|
-
- Install the extra required dependencies by running ``pip install -r requirements_docs.txt`` so you can build a local set.
|
|
18
|
+
- Install the extra required dependencies by running ``pip install -r requirements/requirements_docs.txt`` so you can build a local set.
|
|
19
19
|
|
|
20
20
|
- Then, in a Terminal, enter `cd docs/` and run `sphinx-build -b html source build/html`.
|
|
21
21
|
|
|
@@ -178,6 +178,8 @@ class BindContextBase:
|
|
|
178
178
|
self, state: type[BindStateBase], result: asyncio.Future[Message] | None = None
|
|
179
179
|
) -> None:
|
|
180
180
|
"""Transition the State of the Context, and process the result, if any."""
|
|
181
|
+
# Ensure prev_state is always available, not only during debugging
|
|
182
|
+
prev_state = self._state
|
|
181
183
|
|
|
182
184
|
# if False and result:
|
|
183
185
|
# try:
|
|
@@ -185,10 +187,6 @@ class BindContextBase:
|
|
|
185
187
|
# except exc.BindingError as err:
|
|
186
188
|
# self._fut.set_result(err)
|
|
187
189
|
|
|
188
|
-
if _DBG_MAINTAIN_STATE_CHAIN: # HACK for debugging
|
|
189
|
-
# if prev_state in (None, )
|
|
190
|
-
prev_state = self._state
|
|
191
|
-
|
|
192
190
|
self._state = state(self)
|
|
193
191
|
if not self.is_binding:
|
|
194
192
|
self._is_respondent = None
|
|
@@ -197,6 +195,14 @@ class BindContextBase:
|
|
|
197
195
|
elif state is SuppSendOfferWaitForAccept:
|
|
198
196
|
self._is_respondent = False
|
|
199
197
|
|
|
198
|
+
# Log binding completion transitions
|
|
199
|
+
if isinstance(
|
|
200
|
+
self._state, (RespHasBoundAsRespondent, SuppHasBoundAsSupplicant)
|
|
201
|
+
):
|
|
202
|
+
_LOGGER.info(
|
|
203
|
+
f"{self._dev.id}: Binding process completed: {type(prev_state).__name__} -> {state.__name__} (role: {self.role})"
|
|
204
|
+
)
|
|
205
|
+
|
|
200
206
|
if _DBG_MAINTAIN_STATE_CHAIN: # HACK for debugging
|
|
201
207
|
setattr(self._state, "_prev_state", prev_state) # noqa: B010
|
|
202
208
|
|
|
@@ -663,6 +669,10 @@ class RespHasBoundAsRespondent(BindStateBase):
|
|
|
663
669
|
|
|
664
670
|
_attr_role = BindRole.IS_DORMANT
|
|
665
671
|
|
|
672
|
+
def __init__(self, context: BindContextBase) -> None:
|
|
673
|
+
super().__init__(context)
|
|
674
|
+
_LOGGER.info(f"{context._dev.id}: Binding completed as respondent")
|
|
675
|
+
|
|
666
676
|
|
|
667
677
|
class RespIsWaitingForAddenda(_DevIsWaitingForMsg, BindStateBase):
|
|
668
678
|
"""Respondent has received a Confirm & is waiting for an Addenda."""
|
|
@@ -715,6 +725,10 @@ class SuppHasBoundAsSupplicant(BindStateBase):
|
|
|
715
725
|
|
|
716
726
|
_attr_role = BindRole.IS_DORMANT
|
|
717
727
|
|
|
728
|
+
def __init__(self, context: BindContextBase) -> None:
|
|
729
|
+
super().__init__(context)
|
|
730
|
+
_LOGGER.info(f"{context._dev.id}: Binding completed as supplicant")
|
|
731
|
+
|
|
718
732
|
|
|
719
733
|
class SuppIsReadyToSendAddenda(
|
|
720
734
|
_DevIsReadyToSendCmd, BindStateBase
|
|
@@ -334,7 +334,7 @@ class MessageIndex:
|
|
|
334
334
|
payload_keys(msg.payload),
|
|
335
335
|
),
|
|
336
336
|
)
|
|
337
|
-
_LOGGER.debug(f"Added {msg} to gwy.msg_db")
|
|
337
|
+
# _LOGGER.debug(f"Added {msg} to gwy.msg_db")
|
|
338
338
|
|
|
339
339
|
return _old_msgs[0] if _old_msgs else None
|
|
340
340
|
|
|
@@ -435,7 +435,7 @@ class MessageIndex:
|
|
|
435
435
|
|
|
436
436
|
def qry_dtms(self, **kwargs: bool | dt | str) -> list[Any]:
|
|
437
437
|
"""
|
|
438
|
-
Select from the
|
|
438
|
+
Select from the MessageIndex a list of dtms that match the provided arguments.
|
|
439
439
|
|
|
440
440
|
:param kwargs: data table field names and criteria
|
|
441
441
|
:return: list of unformatted dtms that match, useful for msg lookup, or an empty list if 0 matches
|
|
@@ -120,7 +120,7 @@ _LOGGER = logging.getLogger(__name__)
|
|
|
120
120
|
|
|
121
121
|
class Actuator(DeviceHeat): # 3EF0, 3EF1 (for 10:/13:)
|
|
122
122
|
# .I --- 13:109598 --:------ 13:109598 3EF0 003 00C8FF # event-driven, 00/C8
|
|
123
|
-
# RP --- 13:109598 18:002563 --:------ 0008 002 00C8 # 00/C8, as
|
|
123
|
+
# RP --- 13:109598 18:002563 --:------ 0008 002 00C8 # 00/C8, as above
|
|
124
124
|
# RP --- 13:109598 18:002563 --:------ 3EF1 007 0000BF-00BFC8FF # 00/C8, as above
|
|
125
125
|
|
|
126
126
|
# RP --- 10:048122 18:140805 --:------ 3EF1 007 007FFF-003C2A10 # 10:s only RP, always 7FFF
|
|
@@ -668,11 +668,8 @@ class OtbGateway(Actuator, HeatDemand): # OTB (10): 3220 (22D9, others)
|
|
|
668
668
|
self._child_id = FC # NOTE: domain_id
|
|
669
669
|
|
|
670
670
|
# TODO(eb): cleanup
|
|
671
|
-
# should fix src/ramses_rf/database.py _add_record try/except when activating next line
|
|
672
671
|
if self._gwy.msg_db:
|
|
673
|
-
self._add_record(
|
|
674
|
-
address=self.addr, code=Code._3220, verb="RP"
|
|
675
|
-
) # << essential?
|
|
672
|
+
self._add_record(address=self.addr, code=Code._3220, verb="RP")
|
|
676
673
|
# adds a "sim" RP opentherm_msg to the SQLite MessageIndex with code _3220
|
|
677
674
|
# causes exc when fetching ALL, when no "real" msg was added to _msgs_. We skip those.
|
|
678
675
|
else:
|
|
@@ -1411,7 +1408,7 @@ class UfhCircuit(Child, Entity): # FIXME
|
|
|
1411
1408
|
def __init__(self, ufc: UfhController, ufh_idx: str) -> None:
|
|
1412
1409
|
super().__init__(ufc._gwy)
|
|
1413
1410
|
|
|
1414
|
-
# FIXME:
|
|
1411
|
+
# FIXME: gwy.msg_db entities must know their parent device ID and their own idx
|
|
1415
1412
|
self._z_id = ufc.id
|
|
1416
1413
|
self._z_idx = ufh_idx
|
|
1417
1414
|
|
|
@@ -67,8 +67,7 @@ if TYPE_CHECKING:
|
|
|
67
67
|
|
|
68
68
|
|
|
69
69
|
_QOS_TX_LIMIT = 12 # TODO: needs work
|
|
70
|
-
_ID_SLICE = 9
|
|
71
|
-
_SQL_SLICE = 12 # msg_db dst field query 12
|
|
70
|
+
_ID_SLICE = 9
|
|
72
71
|
_SZ_LAST_PKT: Final = "last_msg"
|
|
73
72
|
_SZ_NEXT_DUE: Final = "next_due"
|
|
74
73
|
_SZ_TIMEOUT: Final = "timeout"
|
|
@@ -248,6 +247,7 @@ class _MessageDB(_Entity):
|
|
|
248
247
|
"For %s (z_id %s) add msg %s, src %s, dst %s to msg_db.",
|
|
249
248
|
self.id,
|
|
250
249
|
self._z_id,
|
|
250
|
+
msg,
|
|
251
251
|
msg.src,
|
|
252
252
|
msg.dst,
|
|
253
253
|
)
|
|
@@ -291,7 +291,7 @@ class _MessageDB(_Entity):
|
|
|
291
291
|
|
|
292
292
|
@property
|
|
293
293
|
def _msg_list(self) -> list[Message]:
|
|
294
|
-
"""Return a flattened list of all messages logged on device."""
|
|
294
|
+
"""Return a flattened list of all messages logged on this device."""
|
|
295
295
|
# (only) used in gateway.py#get_state() and in tests/tests/test_eavesdrop_schema.py
|
|
296
296
|
if self._gwy.msg_db:
|
|
297
297
|
msg_list_qry: list[Message] = []
|
|
@@ -302,6 +302,8 @@ class _MessageDB(_Entity):
|
|
|
302
302
|
# safeguard against lookup failures ("sim" packets?)
|
|
303
303
|
msg_list_qry.append(self._msgs[c])
|
|
304
304
|
else:
|
|
305
|
+
# evohome has these errors
|
|
306
|
+
# _msg_list could not fetch self._msgs[7FFF] for 18:072981 (z_id 18:072981)
|
|
305
307
|
_LOGGER.debug(
|
|
306
308
|
"_msg_list could not fetch self._msgs[%s] for %s (z_id %s)",
|
|
307
309
|
c,
|
|
@@ -428,7 +430,7 @@ class _MessageDB(_Entity):
|
|
|
428
430
|
:param code: filter messages by Code or a tuple of Codes, optional
|
|
429
431
|
:param verb: filter on I, RQ, RP, optional, only with a single Code
|
|
430
432
|
:param key: value keyword to retrieve, not together with verb RQ
|
|
431
|
-
:param kwargs:
|
|
433
|
+
:param kwargs: extra filter, e.g. zone_idx='01'
|
|
432
434
|
:return: a dict containing key: value pairs, or a list of those
|
|
433
435
|
"""
|
|
434
436
|
assert not isinstance(code, tuple) or verb is None, (
|
|
@@ -444,7 +446,9 @@ class _MessageDB(_Entity):
|
|
|
444
446
|
key = None
|
|
445
447
|
try:
|
|
446
448
|
if self._gwy.msg_db: # central SQLite MessageIndex, use verb= kwarg
|
|
447
|
-
code = Code(
|
|
449
|
+
code = Code(
|
|
450
|
+
self._msg_qry_by_code_key(code, key, **kwargs, verb=verb)
|
|
451
|
+
)
|
|
448
452
|
msg = self._msgs.get(code)
|
|
449
453
|
else: # deprecated lookup in nested _msgz
|
|
450
454
|
msgs = self._msgz[code][verb]
|
|
@@ -456,7 +460,9 @@ class _MessageDB(_Entity):
|
|
|
456
460
|
msgs = [m for m in self._msgs.values() if m.code in code]
|
|
457
461
|
msg = max(msgs) if msgs else None
|
|
458
462
|
# return highest = latest? value found in code:value pairs
|
|
459
|
-
else:
|
|
463
|
+
else: # single Code
|
|
464
|
+
# for Zones, this doesn't work, returns first result = often wrong
|
|
465
|
+
# TODO fix in _msg_qry_by_code_key()
|
|
460
466
|
msg = self._msgs.get(code)
|
|
461
467
|
|
|
462
468
|
return self._msg_value_msg(msg, key=key, **kwargs)
|
|
@@ -531,19 +537,37 @@ class _MessageDB(_Entity):
|
|
|
531
537
|
|
|
532
538
|
:return: list of Codes or empty list when query returned empty
|
|
533
539
|
"""
|
|
540
|
+
|
|
534
541
|
if self._gwy.msg_db:
|
|
535
542
|
# SQLite query on MessageIndex
|
|
536
|
-
sql = """
|
|
537
|
-
SELECT code from messages WHERE verb in (' I', 'RP')
|
|
538
|
-
AND (src = ? OR dst = ?)
|
|
539
|
-
"""
|
|
540
543
|
res: list[Code] = []
|
|
544
|
+
if self.id[_ID_SLICE:] == "_HW":
|
|
545
|
+
sql = """
|
|
546
|
+
SELECT code from messages WHERE
|
|
547
|
+
verb in (' I', 'RP')
|
|
548
|
+
AND (src = ? OR dst = ?)
|
|
549
|
+
AND (ctx IN ('FC', 'FA', 'F9', 'FA') OR plk LIKE ?)
|
|
550
|
+
"""
|
|
551
|
+
_ctx_qry = "%dhw_idx%" # syntax error ?
|
|
552
|
+
else:
|
|
553
|
+
sql = """
|
|
554
|
+
SELECT code from messages WHERE
|
|
555
|
+
verb in (' I', 'RP')
|
|
556
|
+
AND (src = ? OR dst = ?)
|
|
557
|
+
AND ctx LIKE ?
|
|
558
|
+
"""
|
|
559
|
+
_ctx_qry = f"%{self.id[_ID_SLICE + 1 :]}%"
|
|
541
560
|
|
|
542
561
|
for rec in self._gwy.msg_db.qry_field(
|
|
543
|
-
sql, (self.id[:
|
|
562
|
+
sql, (self.id[:_ID_SLICE], self.id[:_ID_SLICE], _ctx_qry)
|
|
544
563
|
):
|
|
545
|
-
_LOGGER.debug(
|
|
546
|
-
|
|
564
|
+
_LOGGER.debug(
|
|
565
|
+
"Fetched from index: %s for %s (z_id %s)",
|
|
566
|
+
rec[0],
|
|
567
|
+
self.id,
|
|
568
|
+
self._z_id,
|
|
569
|
+
)
|
|
570
|
+
# Example: "Fetched from index: code 1FD4 for 01:123456 (z_id 01)"
|
|
547
571
|
res.append(Code(str(rec[0])))
|
|
548
572
|
return res
|
|
549
573
|
else:
|
|
@@ -566,32 +590,48 @@ class _MessageDB(_Entity):
|
|
|
566
590
|
:return: Code of most recent query result message or None when query returned empty
|
|
567
591
|
"""
|
|
568
592
|
if self._gwy.msg_db:
|
|
569
|
-
code_qry: str = ""
|
|
593
|
+
code_qry: str = "= "
|
|
570
594
|
if code is None:
|
|
571
|
-
code_qry = "
|
|
595
|
+
code_qry = "LIKE '%'" # wildcard
|
|
572
596
|
elif isinstance(code, tuple):
|
|
573
597
|
for cd in code:
|
|
574
598
|
code_qry += f"'{str(cd)}' OR code = '"
|
|
575
599
|
code_qry = code_qry[:-13] # trim last OR
|
|
576
600
|
else:
|
|
577
|
-
code_qry
|
|
578
|
-
key = "*" if key is None else f"%{key}%"
|
|
601
|
+
code_qry += str(code)
|
|
579
602
|
if kwargs["verb"] and kwargs["verb"] in (" I", "RP"):
|
|
580
603
|
vb = f"('{str(kwargs['verb'])}',)"
|
|
581
604
|
else:
|
|
582
605
|
vb = "(' I', 'RP',)"
|
|
606
|
+
ctx_qry = "%"
|
|
607
|
+
if kwargs["zone_idx"]:
|
|
608
|
+
ctx_qry = f"%{kwargs['zone_idx']}%"
|
|
609
|
+
elif kwargs["dhw_idx"]: # DHW
|
|
610
|
+
ctx_qry = f"%{kwargs['dhw_idx']}%"
|
|
611
|
+
key_qry = "%" if key is None else f"%{key}%"
|
|
612
|
+
|
|
583
613
|
# SQLite query on MessageIndex
|
|
584
614
|
sql = """
|
|
585
|
-
SELECT dtm, code from messages WHERE
|
|
615
|
+
SELECT dtm, code from messages WHERE
|
|
616
|
+
verb in ?
|
|
586
617
|
AND (src = ? OR dst = ?)
|
|
587
|
-
AND (code
|
|
618
|
+
AND (code ?)
|
|
619
|
+
AND (ctx LIKE ?)
|
|
588
620
|
AND (plk LIKE ?)
|
|
589
621
|
"""
|
|
590
622
|
latest: dt = dt(0, 0, 0)
|
|
591
623
|
res = None
|
|
592
624
|
|
|
593
625
|
for rec in self._gwy.msg_db.qry_field(
|
|
594
|
-
sql,
|
|
626
|
+
sql,
|
|
627
|
+
(
|
|
628
|
+
vb,
|
|
629
|
+
self.id[:_ID_SLICE],
|
|
630
|
+
self.id[:_ID_SLICE],
|
|
631
|
+
code_qry,
|
|
632
|
+
ctx_qry,
|
|
633
|
+
key_qry,
|
|
634
|
+
),
|
|
595
635
|
):
|
|
596
636
|
_LOGGER.debug(
|
|
597
637
|
"_msg_qry_by_code_key fetched rec: %s, code: %s", rec, code_qry
|
|
@@ -654,7 +694,7 @@ class _MessageDB(_Entity):
|
|
|
654
694
|
# """SELECT code from messages WHERE verb in (' I', 'RP') AND (src = ? OR dst = ?)
|
|
655
695
|
# AND (code = '31DA' OR ...) AND (plk LIKE '%{SZ_FAN_INFO}%' OR ...)""" = 2 params
|
|
656
696
|
for rec in self._gwy.msg_db.qry_field(
|
|
657
|
-
sql, (self.id[:
|
|
697
|
+
sql, (self.id[:_ID_SLICE], self.id[:_ID_SLICE])
|
|
658
698
|
):
|
|
659
699
|
_pl = self._msgs[Code(rec[0])].payload
|
|
660
700
|
# add payload dict to res(ults)
|
|
@@ -694,24 +734,38 @@ class _MessageDB(_Entity):
|
|
|
694
734
|
# _LOGGER.warning("Missing MessageIndex")
|
|
695
735
|
# raise NotImplementedError
|
|
696
736
|
|
|
697
|
-
if self.id[:3] == "18:": # HGI, confirm this is correct, tests suggest so
|
|
698
|
-
|
|
737
|
+
# if self.id[:3] == "18:": # HGI, confirm this is correct, tests suggest so
|
|
738
|
+
# return {}
|
|
699
739
|
|
|
700
|
-
|
|
701
|
-
SELECT dtm from messages WHERE verb in (' I', 'RP') AND (src = ? OR dst = ?)
|
|
702
|
-
"""
|
|
703
|
-
|
|
704
|
-
# handy routine to debug dict creation, see test_systems.py
|
|
740
|
+
# a routine to debug dict creation, see test_systems.py:
|
|
705
741
|
# print(f"Create _msgs for {self.id}:")
|
|
706
742
|
# results = self._gwy.msg_db._cu.execute("SELECT dtm, src, code from messages WHERE verb in (' I', 'RP') and code is '3150'")
|
|
707
743
|
# for r in results:
|
|
708
744
|
# print(r)
|
|
709
745
|
|
|
710
|
-
|
|
746
|
+
if self.id[_ID_SLICE:] == "_HW":
|
|
747
|
+
sql = """
|
|
748
|
+
SELECT dtm from messages WHERE
|
|
749
|
+
verb in (' I', 'RP')
|
|
750
|
+
AND (src = ? OR dst = ?)
|
|
751
|
+
AND (ctx IN ('FC', 'FA', 'F9', 'FA') OR plk LIKE ?)
|
|
752
|
+
"""
|
|
753
|
+
_ctx_qry = "%dhw_idx%"
|
|
754
|
+
# TODO add Children messages? self.ctl.dhw
|
|
755
|
+
else:
|
|
756
|
+
sql = """
|
|
757
|
+
SELECT dtm from messages WHERE
|
|
758
|
+
verb in (' I', 'RP')
|
|
759
|
+
AND (src = ? OR dst = ?)
|
|
760
|
+
AND ctx LIKE ?
|
|
761
|
+
"""
|
|
762
|
+
_ctx_qry = f"%{self.id[_ID_SLICE + 1 :]}%"
|
|
763
|
+
|
|
764
|
+
_msg_dict = { # since 0.52.3 use ctx (context) instead of just the address
|
|
711
765
|
m.code: m
|
|
712
766
|
for m in self._gwy.msg_db.qry(
|
|
713
|
-
sql, (self.id[:
|
|
714
|
-
) # e.g. 01:123456_HW
|
|
767
|
+
sql, (self.id[:_ID_SLICE], self.id[:_ID_SLICE], _ctx_qry)
|
|
768
|
+
) # e.g. 01:123456_HW, 01:123456_02 (Zone)
|
|
715
769
|
}
|
|
716
770
|
# if CTL, remove 3150, 3220 heat_demand, both are only stored on children
|
|
717
771
|
# HACK
|
|
@@ -786,7 +840,7 @@ class _Discovery(_MessageDB):
|
|
|
786
840
|
code: CODES_SCHEMA[code][SZ_NAME]
|
|
787
841
|
for code in sorted(
|
|
788
842
|
self._gwy.msg_db.get_rp_codes(
|
|
789
|
-
(self.id[:
|
|
843
|
+
(self.id[:_ID_SLICE], self.id[:_ID_SLICE])
|
|
790
844
|
)
|
|
791
845
|
)
|
|
792
846
|
if self._is_not_deprecated_cmd(code)
|
|
@@ -818,7 +872,7 @@ class _Discovery(_MessageDB):
|
|
|
818
872
|
AND (src = ? OR dst = ?)
|
|
819
873
|
"""
|
|
820
874
|
for rec in self._gwy.msg_db.qry_field(
|
|
821
|
-
sql, (self.id[:
|
|
875
|
+
sql, (self.id[:_ID_SLICE], self.id[:_ID_SLICE])
|
|
822
876
|
):
|
|
823
877
|
_LOGGER.debug("Fetched OT ctx from index: %s", rec[0])
|
|
824
878
|
res.append(rec[0])
|
|
@@ -949,8 +1003,8 @@ class _Discovery(_MessageDB):
|
|
|
949
1003
|
sql,
|
|
950
1004
|
(
|
|
951
1005
|
task[_SZ_COMMAND].code,
|
|
952
|
-
self.tcs.id[:_ID_SLICE],
|
|
953
|
-
self.tcs.id[:_ID_SLICE],
|
|
1006
|
+
self.tcs.id[:_ID_SLICE],
|
|
1007
|
+
self.tcs.id[:_ID_SLICE],
|
|
954
1008
|
),
|
|
955
1009
|
)[0] # expect 1 Message in returned tuple
|
|
956
1010
|
else: # TODO(eb) remove next Q1 2026
|
|
@@ -233,7 +233,7 @@ class DhwZone(ZoneSchedule): # CS92A
|
|
|
233
233
|
# def eavesdrop_dhw_sensor(this: Message, *, prev: Message | None = None) -> None:
|
|
234
234
|
# """Eavesdrop packets, or pairs of packets, to maintain the system state.
|
|
235
235
|
|
|
236
|
-
# There are only 2 ways to
|
|
236
|
+
# There are only 2 ways to find a controller's DHW sensor:
|
|
237
237
|
# 1. The 10A0 RQ/RP *from/to a 07:* (1x/4h) - reliable
|
|
238
238
|
# 2. Use sensor temp matching - non-deterministic
|
|
239
239
|
|
|
@@ -34,6 +34,7 @@ from .schemas import (
|
|
|
34
34
|
SZ_DISABLE_QOS,
|
|
35
35
|
SZ_DISABLE_SENDING,
|
|
36
36
|
SZ_ENFORCE_KNOWN_LIST,
|
|
37
|
+
SZ_LOG_ALL_MQTT,
|
|
37
38
|
SZ_PACKET_LOG,
|
|
38
39
|
SZ_PORT_CONFIG,
|
|
39
40
|
SZ_PORT_NAME,
|
|
@@ -114,6 +115,7 @@ class Engine:
|
|
|
114
115
|
self._exclude,
|
|
115
116
|
)
|
|
116
117
|
self._sqlite_index = kwargs.pop(SZ_SQLITE_INDEX, False) # default True?
|
|
118
|
+
self._log_all_mqtt = kwargs.pop(SZ_LOG_ALL_MQTT, False)
|
|
117
119
|
self._kwargs: dict[str, Any] = kwargs # HACK
|
|
118
120
|
|
|
119
121
|
self._engine_lock = Lock() # FIXME: threading lock, or asyncio lock?
|
|
@@ -197,6 +199,7 @@ class Engine:
|
|
|
197
199
|
self._protocol,
|
|
198
200
|
disable_sending=self._disable_sending,
|
|
199
201
|
loop=self._loop,
|
|
202
|
+
log_all=self._log_all_mqtt,
|
|
200
203
|
**pkt_source,
|
|
201
204
|
**self._kwargs, # HACK: odd/misc params, e.g. comms_params
|
|
202
205
|
)
|
|
@@ -162,6 +162,14 @@ class StdOutFilter(logging.Filter): # record.levelno < logging.WARNING
|
|
|
162
162
|
return record.levelno < logging.WARNING
|
|
163
163
|
|
|
164
164
|
|
|
165
|
+
class BlockMqttFilter(logging.Filter):
|
|
166
|
+
"""Block mqtt traffic"""
|
|
167
|
+
|
|
168
|
+
def filter(self, record: logging.LogRecord) -> bool:
|
|
169
|
+
"""Return True if the record is to be processed."""
|
|
170
|
+
return not record.getMessage().startswith("mq Rx: ")
|
|
171
|
+
|
|
172
|
+
|
|
165
173
|
class TimedRotatingFileHandler(_TimedRotatingFileHandler):
|
|
166
174
|
def __init__(self, *args: Any, **kwargs: Any) -> None:
|
|
167
175
|
super().__init__(*args, **kwargs)
|