nwp500-python 9.7.0__tar.gz → 9.9.0__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.
- {nwp500_python-9.7.0 → nwp500_python-9.9.0}/CHANGELOG.rst +84 -0
- {nwp500_python-9.7.0/src/nwp500_python.egg-info → nwp500_python-9.9.0}/PKG-INFO +1 -1
- {nwp500_python-9.7.0 → nwp500_python-9.9.0}/docs/explanation/simulator.rst +5 -1
- {nwp500_python-9.7.0 → nwp500_python-9.9.0}/docs/how-to/calibrate-simulator.rst +61 -6
- {nwp500_python-9.7.0 → nwp500_python-9.9.0}/docs/reference/python_api/sim.rst +7 -3
- {nwp500_python-9.7.0 → nwp500_python-9.9.0}/src/nwp500/sim/api.py +1 -5
- {nwp500_python-9.7.0 → nwp500_python-9.9.0}/src/nwp500/sim/calibration.py +570 -132
- {nwp500_python-9.7.0 → nwp500_python-9.9.0}/src/nwp500/sim/decay.py +29 -1
- {nwp500_python-9.7.0 → nwp500_python-9.9.0}/src/nwp500/sim/params.py +17 -0
- {nwp500_python-9.7.0 → nwp500_python-9.9.0}/src/nwp500/sim/physics/compressor.py +12 -2
- {nwp500_python-9.7.0 → nwp500_python-9.9.0}/src/nwp500/sim/physics/tank.py +68 -0
- {nwp500_python-9.7.0 → nwp500_python-9.9.0}/src/nwp500/sim/tank_physics.py +2 -0
- nwp500_python-9.9.0/src/nwp500/sim_calibrate.py +1245 -0
- {nwp500_python-9.7.0 → nwp500_python-9.9.0/src/nwp500_python.egg-info}/PKG-INFO +1 -1
- {nwp500_python-9.7.0 → nwp500_python-9.9.0}/src/nwp500_python.egg-info/SOURCES.txt +1 -0
- {nwp500_python-9.7.0 → nwp500_python-9.9.0}/src/nwp500_python.egg-info/scm_file_list.json +1 -0
- nwp500_python-9.9.0/src/nwp500_python.egg-info/scm_version.json +8 -0
- nwp500_python-9.9.0/tests/test_sim_bottom_loss.py +665 -0
- nwp500_python-9.9.0/tests/test_sim_calibrate.py +1388 -0
- {nwp500_python-9.7.0 → nwp500_python-9.9.0}/tests/test_sim_change_history.py +45 -0
- nwp500_python-9.7.0/src/nwp500/sim_calibrate.py +0 -517
- nwp500_python-9.7.0/src/nwp500_python.egg-info/scm_version.json +0 -8
- nwp500_python-9.7.0/tests/test_sim_calibrate.py +0 -608
- {nwp500_python-9.7.0 → nwp500_python-9.9.0}/.coveragerc +0 -0
- {nwp500_python-9.7.0 → nwp500_python-9.9.0}/.github/RESOLVING_PR_COMMENTS.md +0 -0
- {nwp500_python-9.7.0 → nwp500_python-9.9.0}/.github/copilot-instructions.md +0 -0
- {nwp500_python-9.7.0 → nwp500_python-9.9.0}/.github/workflows/ci.yml +0 -0
- {nwp500_python-9.7.0 → nwp500_python-9.9.0}/.github/workflows/release.yml +0 -0
- {nwp500_python-9.7.0 → nwp500_python-9.9.0}/.gitignore +0 -0
- {nwp500_python-9.7.0 → nwp500_python-9.9.0}/.pre-commit-config.yaml +0 -0
- {nwp500_python-9.7.0 → nwp500_python-9.9.0}/.readthedocs.yml +0 -0
- {nwp500_python-9.7.0 → nwp500_python-9.9.0}/AUTHORS.rst +0 -0
- {nwp500_python-9.7.0 → nwp500_python-9.9.0}/CONTRIBUTING.rst +0 -0
- {nwp500_python-9.7.0 → nwp500_python-9.9.0}/LICENSE.txt +0 -0
- {nwp500_python-9.7.0 → nwp500_python-9.9.0}/Makefile +0 -0
- {nwp500_python-9.7.0 → nwp500_python-9.9.0}/README.rst +0 -0
- {nwp500_python-9.7.0 → nwp500_python-9.9.0}/RELEASE.md +0 -0
- {nwp500_python-9.7.0 → nwp500_python-9.9.0}/docs/Makefile +0 -0
- {nwp500_python-9.7.0 → nwp500_python-9.9.0}/docs/_static/.gitignore +0 -0
- {nwp500_python-9.7.0 → nwp500_python-9.9.0}/docs/conf.py +0 -0
- {nwp500_python-9.7.0 → nwp500_python-9.9.0}/docs/explanation/architecture.rst +0 -0
- {nwp500_python-9.7.0 → nwp500_python-9.9.0}/docs/explanation/draws.rst +0 -0
- {nwp500_python-9.7.0 → nwp500_python-9.9.0}/docs/explanation/heating-elements.rst +0 -0
- {nwp500_python-9.7.0 → nwp500_python-9.9.0}/docs/explanation/index.rst +0 -0
- {nwp500_python-9.7.0 → nwp500_python-9.9.0}/docs/explanation/recovery-speed.rst +0 -0
- {nwp500_python-9.7.0 → nwp500_python-9.9.0}/docs/explanation/standby-loss.rst +0 -0
- {nwp500_python-9.7.0 → nwp500_python-9.9.0}/docs/explanation/tank-energy.rst +0 -0
- {nwp500_python-9.7.0 → nwp500_python-9.9.0}/docs/explanation/tou-recovery-cap.rst +0 -0
- {nwp500_python-9.7.0 → nwp500_python-9.9.0}/docs/explanation/unknown-values.rst +0 -0
- {nwp500_python-9.7.0 → nwp500_python-9.9.0}/docs/explanation/what-starts-a-recovery.rst +0 -0
- {nwp500_python-9.7.0 → nwp500_python-9.9.0}/docs/how-to/authenticate.rst +0 -0
- {nwp500_python-9.7.0 → nwp500_python-9.9.0}/docs/how-to/auto-recovery.rst +0 -0
- {nwp500_python-9.7.0 → nwp500_python-9.9.0}/docs/how-to/bluetooth.rst +0 -0
- {nwp500_python-9.7.0 → nwp500_python-9.9.0}/docs/how-to/diagnose-mqtt.rst +0 -0
- {nwp500_python-9.7.0 → nwp500_python-9.9.0}/docs/how-to/home-assistant.rst +0 -0
- {nwp500_python-9.7.0 → nwp500_python-9.9.0}/docs/how-to/index.rst +0 -0
- {nwp500_python-9.7.0 → nwp500_python-9.9.0}/docs/how-to/maintenance.rst +0 -0
- {nwp500_python-9.7.0 → nwp500_python-9.9.0}/docs/how-to/manage-units.rst +0 -0
- {nwp500_python-9.7.0 → nwp500_python-9.9.0}/docs/how-to/monitor-status.rst +0 -0
- {nwp500_python-9.7.0 → nwp500_python-9.9.0}/docs/how-to/optimize-tou.rst +0 -0
- {nwp500_python-9.7.0 → nwp500_python-9.9.0}/docs/how-to/queue-commands.rst +0 -0
- {nwp500_python-9.7.0 → nwp500_python-9.9.0}/docs/how-to/schedule-operation.rst +0 -0
- {nwp500_python-9.7.0 → nwp500_python-9.9.0}/docs/how-to/simulate-heater.rst +0 -0
- {nwp500_python-9.7.0 → nwp500_python-9.9.0}/docs/how-to/track-energy.rst +0 -0
- {nwp500_python-9.7.0 → nwp500_python-9.9.0}/docs/index.rst +0 -0
- {nwp500_python-9.7.0 → nwp500_python-9.9.0}/docs/openapi.yaml +0 -0
- {nwp500_python-9.7.0 → nwp500_python-9.9.0}/docs/project/authors.rst +0 -0
- {nwp500_python-9.7.0 → nwp500_python-9.9.0}/docs/project/changelog.rst +0 -0
- {nwp500_python-9.7.0 → nwp500_python-9.9.0}/docs/project/contributing.rst +0 -0
- {nwp500_python-9.7.0 → nwp500_python-9.9.0}/docs/project/history.rst +0 -0
- {nwp500_python-9.7.0 → nwp500_python-9.9.0}/docs/project/license.rst +0 -0
- {nwp500_python-9.7.0 → nwp500_python-9.9.0}/docs/reference/configuration.rst +0 -0
- {nwp500_python-9.7.0 → nwp500_python-9.9.0}/docs/reference/enumerations.rst +0 -0
- {nwp500_python-9.7.0 → nwp500_python-9.9.0}/docs/reference/index.rst +0 -0
- {nwp500_python-9.7.0 → nwp500_python-9.9.0}/docs/reference/installation.rst +0 -0
- {nwp500_python-9.7.0 → nwp500_python-9.9.0}/docs/reference/protocol/data_conversions.rst +0 -0
- {nwp500_python-9.7.0 → nwp500_python-9.9.0}/docs/reference/protocol/device_features.rst +0 -0
- {nwp500_python-9.7.0 → nwp500_python-9.9.0}/docs/reference/protocol/device_status.rst +0 -0
- {nwp500_python-9.7.0 → nwp500_python-9.9.0}/docs/reference/protocol/error_codes.rst +0 -0
- {nwp500_python-9.7.0 → nwp500_python-9.9.0}/docs/reference/protocol/mqtt_protocol.rst +0 -0
- {nwp500_python-9.7.0 → nwp500_python-9.9.0}/docs/reference/protocol/quick_reference.rst +0 -0
- {nwp500_python-9.7.0 → nwp500_python-9.9.0}/docs/reference/protocol/rest_api.rst +0 -0
- {nwp500_python-9.7.0 → nwp500_python-9.9.0}/docs/reference/python_api/api_client.rst +0 -0
- {nwp500_python-9.7.0 → nwp500_python-9.9.0}/docs/reference/python_api/auth_client.rst +0 -0
- {nwp500_python-9.7.0 → nwp500_python-9.9.0}/docs/reference/python_api/cli.rst +0 -0
- {nwp500_python-9.7.0 → nwp500_python-9.9.0}/docs/reference/python_api/events.rst +0 -0
- {nwp500_python-9.7.0 → nwp500_python-9.9.0}/docs/reference/python_api/exceptions.rst +0 -0
- {nwp500_python-9.7.0 → nwp500_python-9.9.0}/docs/reference/python_api/models.rst +0 -0
- {nwp500_python-9.7.0 → nwp500_python-9.9.0}/docs/reference/python_api/mqtt_client.rst +0 -0
- {nwp500_python-9.7.0 → nwp500_python-9.9.0}/docs/reference/simulator-inputs.rst +0 -0
- {nwp500_python-9.7.0 → nwp500_python-9.9.0}/docs/requirements.txt +0 -0
- {nwp500_python-9.7.0 → nwp500_python-9.9.0}/docs/tutorials/getting-started.rst +0 -0
- {nwp500_python-9.7.0 → nwp500_python-9.9.0}/examples/.ruff.toml +0 -0
- {nwp500_python-9.7.0 → nwp500_python-9.9.0}/examples/README.md +0 -0
- {nwp500_python-9.7.0 → nwp500_python-9.9.0}/examples/advanced/air_filter_reset.py +0 -0
- {nwp500_python-9.7.0 → nwp500_python-9.9.0}/examples/advanced/anti_legionella.py +0 -0
- {nwp500_python-9.7.0 → nwp500_python-9.9.0}/examples/advanced/auto_recovery.py +0 -0
- {nwp500_python-9.7.0 → nwp500_python-9.9.0}/examples/advanced/combined_callbacks.py +0 -0
- {nwp500_python-9.7.0 → nwp500_python-9.9.0}/examples/advanced/demand_response.py +0 -0
- {nwp500_python-9.7.0 → nwp500_python-9.9.0}/examples/advanced/device_capabilities.py +0 -0
- {nwp500_python-9.7.0 → nwp500_python-9.9.0}/examples/advanced/device_status_debug.py +0 -0
- {nwp500_python-9.7.0 → nwp500_python-9.9.0}/examples/advanced/energy_analytics.py +0 -0
- {nwp500_python-9.7.0 → nwp500_python-9.9.0}/examples/advanced/error_code_demo.py +0 -0
- {nwp500_python-9.7.0 → nwp500_python-9.9.0}/examples/advanced/firmware_payload_capture.py +0 -0
- {nwp500_python-9.7.0 → nwp500_python-9.9.0}/examples/advanced/mqtt_diagnostics.py +0 -0
- {nwp500_python-9.7.0 → nwp500_python-9.9.0}/examples/advanced/power_control.py +0 -0
- {nwp500_python-9.7.0 → nwp500_python-9.9.0}/examples/advanced/recirculation_control.py +0 -0
- {nwp500_python-9.7.0 → nwp500_python-9.9.0}/examples/advanced/reconnection_demo.py +0 -0
- {nwp500_python-9.7.0 → nwp500_python-9.9.0}/examples/advanced/reservation_schedule.py +0 -0
- {nwp500_python-9.7.0 → nwp500_python-9.9.0}/examples/advanced/simple_auto_recovery.py +0 -0
- {nwp500_python-9.7.0 → nwp500_python-9.9.0}/examples/advanced/token_restoration.py +0 -0
- {nwp500_python-9.7.0 → nwp500_python-9.9.0}/examples/advanced/tou_openei.py +0 -0
- {nwp500_python-9.7.0 → nwp500_python-9.9.0}/examples/advanced/tou_schedule.py +0 -0
- {nwp500_python-9.7.0 → nwp500_python-9.9.0}/examples/advanced/water_reservation.py +0 -0
- {nwp500_python-9.7.0 → nwp500_python-9.9.0}/examples/beginner/01_authentication.py +0 -0
- {nwp500_python-9.7.0 → nwp500_python-9.9.0}/examples/beginner/02_list_devices.py +0 -0
- {nwp500_python-9.7.0 → nwp500_python-9.9.0}/examples/beginner/03_get_status.py +0 -0
- {nwp500_python-9.7.0 → nwp500_python-9.9.0}/examples/beginner/04_set_temperature.py +0 -0
- {nwp500_python-9.7.0 → nwp500_python-9.9.0}/examples/intermediate/advanced_auth_patterns.py +0 -0
- {nwp500_python-9.7.0 → nwp500_python-9.9.0}/examples/intermediate/command_queue.py +0 -0
- {nwp500_python-9.7.0 → nwp500_python-9.9.0}/examples/intermediate/device_status_callback.py +0 -0
- {nwp500_python-9.7.0 → nwp500_python-9.9.0}/examples/intermediate/error_handling.py +0 -0
- {nwp500_python-9.7.0 → nwp500_python-9.9.0}/examples/intermediate/event_driven_control.py +0 -0
- {nwp500_python-9.7.0 → nwp500_python-9.9.0}/examples/intermediate/improved_auth.py +0 -0
- {nwp500_python-9.7.0 → nwp500_python-9.9.0}/examples/intermediate/legacy_auth_constructor.py +0 -0
- {nwp500_python-9.7.0 → nwp500_python-9.9.0}/examples/intermediate/mqtt_realtime_monitoring.py +0 -0
- {nwp500_python-9.7.0 → nwp500_python-9.9.0}/examples/intermediate/periodic_requests.py +0 -0
- {nwp500_python-9.7.0 → nwp500_python-9.9.0}/examples/intermediate/set_mode.py +0 -0
- {nwp500_python-9.7.0 → nwp500_python-9.9.0}/examples/intermediate/vacation_mode.py +0 -0
- {nwp500_python-9.7.0 → nwp500_python-9.9.0}/examples/mask.py +0 -0
- {nwp500_python-9.7.0 → nwp500_python-9.9.0}/examples/simulator/lower-setpoint.json +0 -0
- {nwp500_python-9.7.0 → nwp500_python-9.9.0}/examples/simulator/plan.json +0 -0
- {nwp500_python-9.7.0 → nwp500_python-9.9.0}/examples/simulator/scenario.json +0 -0
- {nwp500_python-9.7.0 → nwp500_python-9.9.0}/examples/testing/periodic_device_info.py +0 -0
- {nwp500_python-9.7.0 → nwp500_python-9.9.0}/examples/testing/simple_periodic_info.py +0 -0
- {nwp500_python-9.7.0 → nwp500_python-9.9.0}/examples/testing/test_api_client.py +0 -0
- {nwp500_python-9.7.0 → nwp500_python-9.9.0}/examples/testing/test_mqtt_connection.py +0 -0
- {nwp500_python-9.7.0 → nwp500_python-9.9.0}/examples/testing/test_mqtt_messaging.py +0 -0
- {nwp500_python-9.7.0 → nwp500_python-9.9.0}/examples/testing/test_periodic_minimal.py +0 -0
- {nwp500_python-9.7.0 → nwp500_python-9.9.0}/pyproject.toml +0 -0
- {nwp500_python-9.7.0 → nwp500_python-9.9.0}/scripts/README.md +0 -0
- {nwp500_python-9.7.0 → nwp500_python-9.9.0}/scripts/bump_version.py +0 -0
- {nwp500_python-9.7.0 → nwp500_python-9.9.0}/scripts/diagnose_mqtt_connection.py +0 -0
- {nwp500_python-9.7.0 → nwp500_python-9.9.0}/scripts/extract_changelog.py +0 -0
- {nwp500_python-9.7.0 → nwp500_python-9.9.0}/scripts/format.py +0 -0
- {nwp500_python-9.7.0 → nwp500_python-9.9.0}/scripts/lint.py +0 -0
- {nwp500_python-9.7.0 → nwp500_python-9.9.0}/scripts/setup-dev.py +0 -0
- {nwp500_python-9.7.0 → nwp500_python-9.9.0}/scripts/validate_version.py +0 -0
- {nwp500_python-9.7.0 → nwp500_python-9.9.0}/setup.cfg +0 -0
- {nwp500_python-9.7.0 → nwp500_python-9.9.0}/setup.py +0 -0
- {nwp500_python-9.7.0 → nwp500_python-9.9.0}/src/nwp500/__init__.py +0 -0
- {nwp500_python-9.7.0 → nwp500_python-9.9.0}/src/nwp500/_base.py +0 -0
- {nwp500_python-9.7.0 → nwp500_python-9.9.0}/src/nwp500/api_client.py +0 -0
- {nwp500_python-9.7.0 → nwp500_python-9.9.0}/src/nwp500/auth.py +0 -0
- {nwp500_python-9.7.0 → nwp500_python-9.9.0}/src/nwp500/ble/__init__.py +0 -0
- {nwp500_python-9.7.0 → nwp500_python-9.9.0}/src/nwp500/ble/__main__.py +0 -0
- {nwp500_python-9.7.0 → nwp500_python-9.9.0}/src/nwp500/ble/client.py +0 -0
- {nwp500_python-9.7.0 → nwp500_python-9.9.0}/src/nwp500/ble/mqtt_adapter.py +0 -0
- {nwp500_python-9.7.0 → nwp500_python-9.9.0}/src/nwp500/ble/protocol.py +0 -0
- {nwp500_python-9.7.0 → nwp500_python-9.9.0}/src/nwp500/cli/__init__.py +0 -0
- {nwp500_python-9.7.0 → nwp500_python-9.9.0}/src/nwp500/cli/__main__.py +0 -0
- {nwp500_python-9.7.0 → nwp500_python-9.9.0}/src/nwp500/cli/ble_backend.py +0 -0
- {nwp500_python-9.7.0 → nwp500_python-9.9.0}/src/nwp500/cli/calibration.py +0 -0
- {nwp500_python-9.7.0 → nwp500_python-9.9.0}/src/nwp500/cli/handlers.py +0 -0
- {nwp500_python-9.7.0 → nwp500_python-9.9.0}/src/nwp500/cli/monitoring.py +0 -0
- {nwp500_python-9.7.0 → nwp500_python-9.9.0}/src/nwp500/cli/output_formatters.py +0 -0
- {nwp500_python-9.7.0 → nwp500_python-9.9.0}/src/nwp500/cli/presentation.py +0 -0
- {nwp500_python-9.7.0 → nwp500_python-9.9.0}/src/nwp500/cli/recording.py +0 -0
- {nwp500_python-9.7.0 → nwp500_python-9.9.0}/src/nwp500/cli/rich_output.py +0 -0
- {nwp500_python-9.7.0 → nwp500_python-9.9.0}/src/nwp500/cli/simulate.py +0 -0
- {nwp500_python-9.7.0 → nwp500_python-9.9.0}/src/nwp500/cli/token_storage.py +0 -0
- {nwp500_python-9.7.0 → nwp500_python-9.9.0}/src/nwp500/command_decorators.py +0 -0
- {nwp500_python-9.7.0 → nwp500_python-9.9.0}/src/nwp500/config.py +0 -0
- {nwp500_python-9.7.0 → nwp500_python-9.9.0}/src/nwp500/converters.py +0 -0
- {nwp500_python-9.7.0 → nwp500_python-9.9.0}/src/nwp500/device_capabilities.py +0 -0
- {nwp500_python-9.7.0 → nwp500_python-9.9.0}/src/nwp500/device_info_cache.py +0 -0
- {nwp500_python-9.7.0 → nwp500_python-9.9.0}/src/nwp500/encoding.py +0 -0
- {nwp500_python-9.7.0 → nwp500_python-9.9.0}/src/nwp500/enums.py +0 -0
- {nwp500_python-9.7.0 → nwp500_python-9.9.0}/src/nwp500/events.py +0 -0
- {nwp500_python-9.7.0 → nwp500_python-9.9.0}/src/nwp500/exceptions.py +0 -0
- {nwp500_python-9.7.0 → nwp500_python-9.9.0}/src/nwp500/factory.py +0 -0
- {nwp500_python-9.7.0 → nwp500_python-9.9.0}/src/nwp500/field_factory.py +0 -0
- {nwp500_python-9.7.0 → nwp500_python-9.9.0}/src/nwp500/models/__init__.py +0 -0
- {nwp500_python-9.7.0 → nwp500_python-9.9.0}/src/nwp500/models/_converters.py +0 -0
- {nwp500_python-9.7.0 → nwp500_python-9.9.0}/src/nwp500/models/account.py +0 -0
- {nwp500_python-9.7.0 → nwp500_python-9.9.0}/src/nwp500/models/device.py +0 -0
- {nwp500_python-9.7.0 → nwp500_python-9.9.0}/src/nwp500/models/diagnostics.py +0 -0
- {nwp500_python-9.7.0 → nwp500_python-9.9.0}/src/nwp500/models/energy.py +0 -0
- {nwp500_python-9.7.0 → nwp500_python-9.9.0}/src/nwp500/models/feature.py +0 -0
- {nwp500_python-9.7.0 → nwp500_python-9.9.0}/src/nwp500/models/firmware.py +0 -0
- {nwp500_python-9.7.0 → nwp500_python-9.9.0}/src/nwp500/models/maintenance.py +0 -0
- {nwp500_python-9.7.0 → nwp500_python-9.9.0}/src/nwp500/models/mqtt_models.py +0 -0
- {nwp500_python-9.7.0 → nwp500_python-9.9.0}/src/nwp500/models/schedule.py +0 -0
- {nwp500_python-9.7.0 → nwp500_python-9.9.0}/src/nwp500/models/status.py +0 -0
- {nwp500_python-9.7.0 → nwp500_python-9.9.0}/src/nwp500/models/tou.py +0 -0
- {nwp500_python-9.7.0 → nwp500_python-9.9.0}/src/nwp500/mqtt/__init__.py +0 -0
- {nwp500_python-9.7.0 → nwp500_python-9.9.0}/src/nwp500/mqtt/_control_commands.py +0 -0
- {nwp500_python-9.7.0 → nwp500_python-9.9.0}/src/nwp500/mqtt/_device_subscriptions.py +0 -0
- {nwp500_python-9.7.0 → nwp500_python-9.9.0}/src/nwp500/mqtt/client.py +0 -0
- {nwp500_python-9.7.0 → nwp500_python-9.9.0}/src/nwp500/mqtt/command_queue.py +0 -0
- {nwp500_python-9.7.0 → nwp500_python-9.9.0}/src/nwp500/mqtt/connection.py +0 -0
- {nwp500_python-9.7.0 → nwp500_python-9.9.0}/src/nwp500/mqtt/control.py +0 -0
- {nwp500_python-9.7.0 → nwp500_python-9.9.0}/src/nwp500/mqtt/diagnostics.py +0 -0
- {nwp500_python-9.7.0 → nwp500_python-9.9.0}/src/nwp500/mqtt/periodic.py +0 -0
- {nwp500_python-9.7.0 → nwp500_python-9.9.0}/src/nwp500/mqtt/reconnection.py +0 -0
- {nwp500_python-9.7.0 → nwp500_python-9.9.0}/src/nwp500/mqtt/state_tracker.py +0 -0
- {nwp500_python-9.7.0 → nwp500_python-9.9.0}/src/nwp500/mqtt/subscriptions.py +0 -0
- {nwp500_python-9.7.0 → nwp500_python-9.9.0}/src/nwp500/mqtt/types.py +0 -0
- {nwp500_python-9.7.0 → nwp500_python-9.9.0}/src/nwp500/mqtt/utils.py +0 -0
- {nwp500_python-9.7.0 → nwp500_python-9.9.0}/src/nwp500/mqtt_events.py +0 -0
- {nwp500_python-9.7.0 → nwp500_python-9.9.0}/src/nwp500/openei.py +0 -0
- {nwp500_python-9.7.0 → nwp500_python-9.9.0}/src/nwp500/py.typed +0 -0
- {nwp500_python-9.7.0 → nwp500_python-9.9.0}/src/nwp500/reservations.py +0 -0
- {nwp500_python-9.7.0 → nwp500_python-9.9.0}/src/nwp500/sim/__init__.py +0 -0
- {nwp500_python-9.7.0 → nwp500_python-9.9.0}/src/nwp500/sim/attribution.py +0 -0
- {nwp500_python-9.7.0 → nwp500_python-9.9.0}/src/nwp500/sim/book.py +0 -0
- {nwp500_python-9.7.0 → nwp500_python-9.9.0}/src/nwp500/sim/circulation.py +0 -0
- {nwp500_python-9.7.0 → nwp500_python-9.9.0}/src/nwp500/sim/codec.py +0 -0
- {nwp500_python-9.7.0 → nwp500_python-9.9.0}/src/nwp500/sim/cold_supply.py +0 -0
- {nwp500_python-9.7.0 → nwp500_python-9.9.0}/src/nwp500/sim/controller.py +0 -0
- {nwp500_python-9.7.0 → nwp500_python-9.9.0}/src/nwp500/sim/defaults.py +0 -0
- {nwp500_python-9.7.0 → nwp500_python-9.9.0}/src/nwp500/sim/delivery.py +0 -0
- {nwp500_python-9.7.0 → nwp500_python-9.9.0}/src/nwp500/sim/draw_forecast.py +0 -0
- {nwp500_python-9.7.0 → nwp500_python-9.9.0}/src/nwp500/sim/engine.py +0 -0
- {nwp500_python-9.7.0 → nwp500_python-9.9.0}/src/nwp500/sim/extensions.py +0 -0
- {nwp500_python-9.7.0 → nwp500_python-9.9.0}/src/nwp500/sim/heat_pump_recovery.py +0 -0
- {nwp500_python-9.7.0 → nwp500_python-9.9.0}/src/nwp500/sim/heating_trajectory.py +0 -0
- {nwp500_python-9.7.0 → nwp500_python-9.9.0}/src/nwp500/sim/inputs.py +0 -0
- {nwp500_python-9.7.0 → nwp500_python-9.9.0}/src/nwp500/sim/location_air.py +0 -0
- {nwp500_python-9.7.0 → nwp500_python-9.9.0}/src/nwp500/sim/meter.py +0 -0
- {nwp500_python-9.7.0 → nwp500_python-9.9.0}/src/nwp500/sim/observed.py +0 -0
- {nwp500_python-9.7.0 → nwp500_python-9.9.0}/src/nwp500/sim/physics/__init__.py +0 -0
- {nwp500_python-9.7.0 → nwp500_python-9.9.0}/src/nwp500/sim/physics/draw.py +0 -0
- {nwp500_python-9.7.0 → nwp500_python-9.9.0}/src/nwp500/sim/physics/element.py +0 -0
- {nwp500_python-9.7.0 → nwp500_python-9.9.0}/src/nwp500/sim/physics/refrigerant.py +0 -0
- {nwp500_python-9.7.0 → nwp500_python-9.9.0}/src/nwp500/sim/profile.py +0 -0
- {nwp500_python-9.7.0 → nwp500_python-9.9.0}/src/nwp500/sim/ready.py +0 -0
- {nwp500_python-9.7.0 → nwp500_python-9.9.0}/src/nwp500/sim/record.py +0 -0
- {nwp500_python-9.7.0 → nwp500_python-9.9.0}/src/nwp500/sim/result.py +0 -0
- {nwp500_python-9.7.0 → nwp500_python-9.9.0}/src/nwp500/sim/schedules.py +0 -0
- {nwp500_python-9.7.0 → nwp500_python-9.9.0}/src/nwp500/sim/tou_triggers.py +0 -0
- {nwp500_python-9.7.0 → nwp500_python-9.9.0}/src/nwp500/sim/units.py +0 -0
- {nwp500_python-9.7.0 → nwp500_python-9.9.0}/src/nwp500/sim_adapters.py +0 -0
- {nwp500_python-9.7.0 → nwp500_python-9.9.0}/src/nwp500/sim_home_assistant.py +0 -0
- {nwp500_python-9.7.0 → nwp500_python-9.9.0}/src/nwp500/sim_live.py +0 -0
- {nwp500_python-9.7.0 → nwp500_python-9.9.0}/src/nwp500/status_history.py +0 -0
- {nwp500_python-9.7.0 → nwp500_python-9.9.0}/src/nwp500/temperature.py +0 -0
- {nwp500_python-9.7.0 → nwp500_python-9.9.0}/src/nwp500/topic_builder.py +0 -0
- {nwp500_python-9.7.0 → nwp500_python-9.9.0}/src/nwp500/tou_schedule.py +0 -0
- {nwp500_python-9.7.0 → nwp500_python-9.9.0}/src/nwp500/unit_system.py +0 -0
- {nwp500_python-9.7.0 → nwp500_python-9.9.0}/src/nwp500/utils.py +0 -0
- {nwp500_python-9.7.0 → nwp500_python-9.9.0}/src/nwp500_python.egg-info/dependency_links.txt +0 -0
- {nwp500_python-9.7.0 → nwp500_python-9.9.0}/src/nwp500_python.egg-info/entry_points.txt +0 -0
- {nwp500_python-9.7.0 → nwp500_python-9.9.0}/src/nwp500_python.egg-info/not-zip-safe +0 -0
- {nwp500_python-9.7.0 → nwp500_python-9.9.0}/src/nwp500_python.egg-info/requires.txt +0 -0
- {nwp500_python-9.7.0 → nwp500_python-9.9.0}/src/nwp500_python.egg-info/top_level.txt +0 -0
- {nwp500_python-9.7.0 → nwp500_python-9.9.0}/tests/_sim_site.py +0 -0
- {nwp500_python-9.7.0 → nwp500_python-9.9.0}/tests/conftest.py +0 -0
- {nwp500_python-9.7.0 → nwp500_python-9.9.0}/tests/fixtures/sim/engine_golden.json +0 -0
- {nwp500_python-9.7.0 → nwp500_python-9.9.0}/tests/fixtures/sim/heater_params.json +0 -0
- {nwp500_python-9.7.0 → nwp500_python-9.9.0}/tests/fixtures/sim/heater_params_fitted.json +0 -0
- {nwp500_python-9.7.0 → nwp500_python-9.9.0}/tests/test_api_endpoints_201.py +0 -0
- {nwp500_python-9.7.0 → nwp500_python-9.9.0}/tests/test_api_helpers.py +0 -0
- {nwp500_python-9.7.0 → nwp500_python-9.9.0}/tests/test_app_queries.py +0 -0
- {nwp500_python-9.7.0 → nwp500_python-9.9.0}/tests/test_auth.py +0 -0
- {nwp500_python-9.7.0 → nwp500_python-9.9.0}/tests/test_auth_session_lifecycle.py +0 -0
- {nwp500_python-9.7.0 → nwp500_python-9.9.0}/tests/test_auth_session_refresh.py +0 -0
- {nwp500_python-9.7.0 → nwp500_python-9.9.0}/tests/test_ble_mqtt_adapter.py +0 -0
- {nwp500_python-9.7.0 → nwp500_python-9.9.0}/tests/test_ble_protocol.py +0 -0
- {nwp500_python-9.7.0 → nwp500_python-9.9.0}/tests/test_bug_fixes.py +0 -0
- {nwp500_python-9.7.0 → nwp500_python-9.9.0}/tests/test_canonical_schedule.py +0 -0
- {nwp500_python-9.7.0 → nwp500_python-9.9.0}/tests/test_cli_basic.py +0 -0
- {nwp500_python-9.7.0 → nwp500_python-9.9.0}/tests/test_cli_calibrate.py +0 -0
- {nwp500_python-9.7.0 → nwp500_python-9.9.0}/tests/test_cli_commands.py +0 -0
- {nwp500_python-9.7.0 → nwp500_python-9.9.0}/tests/test_cli_simulate.py +0 -0
- {nwp500_python-9.7.0 → nwp500_python-9.9.0}/tests/test_cli_tristate_presentation.py +0 -0
- {nwp500_python-9.7.0 → nwp500_python-9.9.0}/tests/test_command_decorators.py +0 -0
- {nwp500_python-9.7.0 → nwp500_python-9.9.0}/tests/test_command_queue.py +0 -0
- {nwp500_python-9.7.0 → nwp500_python-9.9.0}/tests/test_device_capabilities.py +0 -0
- {nwp500_python-9.7.0 → nwp500_python-9.9.0}/tests/test_device_info_cache.py +0 -0
- {nwp500_python-9.7.0 → nwp500_python-9.9.0}/tests/test_device_rest_models.py +0 -0
- {nwp500_python-9.7.0 → nwp500_python-9.9.0}/tests/test_events.py +0 -0
- {nwp500_python-9.7.0 → nwp500_python-9.9.0}/tests/test_exceptions.py +0 -0
- {nwp500_python-9.7.0 → nwp500_python-9.9.0}/tests/test_model_converters.py +0 -0
- {nwp500_python-9.7.0 → nwp500_python-9.9.0}/tests/test_models.py +0 -0
- {nwp500_python-9.7.0 → nwp500_python-9.9.0}/tests/test_mqtt_clean_session_resume.py +0 -0
- {nwp500_python-9.7.0 → nwp500_python-9.9.0}/tests/test_mqtt_client_init.py +0 -0
- {nwp500_python-9.7.0 → nwp500_python-9.9.0}/tests/test_mqtt_control_fail.py +0 -0
- {nwp500_python-9.7.0 → nwp500_python-9.9.0}/tests/test_mqtt_events.py +0 -0
- {nwp500_python-9.7.0 → nwp500_python-9.9.0}/tests/test_mqtt_hypothesis.py +0 -0
- {nwp500_python-9.7.0 → nwp500_python-9.9.0}/tests/test_mqtt_last_will.py +0 -0
- {nwp500_python-9.7.0 → nwp500_python-9.9.0}/tests/test_mqtt_reconnection.py +0 -0
- {nwp500_python-9.7.0 → nwp500_python-9.9.0}/tests/test_mqtt_reconnection_storm.py +0 -0
- {nwp500_python-9.7.0 → nwp500_python-9.9.0}/tests/test_mqtt_reliability.py +0 -0
- {nwp500_python-9.7.0 → nwp500_python-9.9.0}/tests/test_multi_device.py +0 -0
- {nwp500_python-9.7.0 → nwp500_python-9.9.0}/tests/test_navilink_201_enums.py +0 -0
- {nwp500_python-9.7.0 → nwp500_python-9.9.0}/tests/test_openei.py +0 -0
- {nwp500_python-9.7.0 → nwp500_python-9.9.0}/tests/test_protocol_correctness.py +0 -0
- {nwp500_python-9.7.0 → nwp500_python-9.9.0}/tests/test_public_api.py +0 -0
- {nwp500_python-9.7.0 → nwp500_python-9.9.0}/tests/test_reservation_validation.py +0 -0
- {nwp500_python-9.7.0 → nwp500_python-9.9.0}/tests/test_reservations.py +0 -0
- {nwp500_python-9.7.0 → nwp500_python-9.9.0}/tests/test_sim_adapters.py +0 -0
- {nwp500_python-9.7.0 → nwp500_python-9.9.0}/tests/test_sim_api.py +0 -0
- {nwp500_python-9.7.0 → nwp500_python-9.9.0}/tests/test_sim_book.py +0 -0
- {nwp500_python-9.7.0 → nwp500_python-9.9.0}/tests/test_sim_book_history.py +0 -0
- {nwp500_python-9.7.0 → nwp500_python-9.9.0}/tests/test_sim_calibration.py +0 -0
- {nwp500_python-9.7.0 → nwp500_python-9.9.0}/tests/test_sim_circulation.py +0 -0
- {nwp500_python-9.7.0 → nwp500_python-9.9.0}/tests/test_sim_codec.py +0 -0
- {nwp500_python-9.7.0 → nwp500_python-9.9.0}/tests/test_sim_cold_supply.py +0 -0
- {nwp500_python-9.7.0 → nwp500_python-9.9.0}/tests/test_sim_controller.py +0 -0
- {nwp500_python-9.7.0 → nwp500_python-9.9.0}/tests/test_sim_defaults.py +0 -0
- {nwp500_python-9.7.0 → nwp500_python-9.9.0}/tests/test_sim_draw_forecast.py +0 -0
- {nwp500_python-9.7.0 → nwp500_python-9.9.0}/tests/test_sim_draw_loss.py +0 -0
- {nwp500_python-9.7.0 → nwp500_python-9.9.0}/tests/test_sim_element.py +0 -0
- {nwp500_python-9.7.0 → nwp500_python-9.9.0}/tests/test_sim_element_fit.py +0 -0
- {nwp500_python-9.7.0 → nwp500_python-9.9.0}/tests/test_sim_forecast.py +0 -0
- {nwp500_python-9.7.0 → nwp500_python-9.9.0}/tests/test_sim_golden.py +0 -0
- {nwp500_python-9.7.0 → nwp500_python-9.9.0}/tests/test_sim_home_assistant.py +0 -0
- {nwp500_python-9.7.0 → nwp500_python-9.9.0}/tests/test_sim_hot_water.py +0 -0
- {nwp500_python-9.7.0 → nwp500_python-9.9.0}/tests/test_sim_import_contract.py +0 -0
- {nwp500_python-9.7.0 → nwp500_python-9.9.0}/tests/test_sim_live.py +0 -0
- {nwp500_python-9.7.0 → nwp500_python-9.9.0}/tests/test_sim_location_air.py +0 -0
- {nwp500_python-9.7.0 → nwp500_python-9.9.0}/tests/test_sim_meter.py +0 -0
- {nwp500_python-9.7.0 → nwp500_python-9.9.0}/tests/test_sim_no_clock_no_state.py +0 -0
- {nwp500_python-9.7.0 → nwp500_python-9.9.0}/tests/test_sim_observed.py +0 -0
- {nwp500_python-9.7.0 → nwp500_python-9.9.0}/tests/test_sim_profile.py +0 -0
- {nwp500_python-9.7.0 → nwp500_python-9.9.0}/tests/test_sim_readiness.py +0 -0
- {nwp500_python-9.7.0 → nwp500_python-9.9.0}/tests/test_sim_readiness_fit.py +0 -0
- {nwp500_python-9.7.0 → nwp500_python-9.9.0}/tests/test_sim_ready.py +0 -0
- {nwp500_python-9.7.0 → nwp500_python-9.9.0}/tests/test_sim_ready_api.py +0 -0
- {nwp500_python-9.7.0 → nwp500_python-9.9.0}/tests/test_sim_replay.py +0 -0
- {nwp500_python-9.7.0 → nwp500_python-9.9.0}/tests/test_sim_schedules.py +0 -0
- {nwp500_python-9.7.0 → nwp500_python-9.9.0}/tests/test_sim_tank_physics.py +0 -0
- {nwp500_python-9.7.0 → nwp500_python-9.9.0}/tests/test_status_history.py +0 -0
- {nwp500_python-9.7.0 → nwp500_python-9.9.0}/tests/test_temperature_converters.py +0 -0
- {nwp500_python-9.7.0 → nwp500_python-9.9.0}/tests/test_threading_model.py +0 -0
- {nwp500_python-9.7.0 → nwp500_python-9.9.0}/tests/test_token_storage.py +0 -0
- {nwp500_python-9.7.0 → nwp500_python-9.9.0}/tests/test_tou_api.py +0 -0
- {nwp500_python-9.7.0 → nwp500_python-9.9.0}/tests/test_tou_schedule.py +0 -0
- {nwp500_python-9.7.0 → nwp500_python-9.9.0}/tests/test_unit_switching.py +0 -0
- {nwp500_python-9.7.0 → nwp500_python-9.9.0}/tests/test_unit_system_process_wide.py +0 -0
- {nwp500_python-9.7.0 → nwp500_python-9.9.0}/tests/test_utility_modules.py +0 -0
- {nwp500_python-9.7.0 → nwp500_python-9.9.0}/tests/test_utils.py +0 -0
- {nwp500_python-9.7.0 → nwp500_python-9.9.0}/tox.ini +0 -0
- {nwp500_python-9.7.0 → nwp500_python-9.9.0}/uv.lock +0 -0
|
@@ -2,6 +2,90 @@
|
|
|
2
2
|
Changelog
|
|
3
3
|
=========
|
|
4
4
|
|
|
5
|
+
Version 9.9.0 (2026-10-22)
|
|
6
|
+
==========================
|
|
7
|
+
|
|
8
|
+
Added
|
|
9
|
+
-----
|
|
10
|
+
- **A bottom loss in the standby model** (#187). Over one installation's 407
|
|
11
|
+
quiet windows across ten months, a window that opens stratified loses
|
|
12
|
+
heat at the bottom: its gap widens, its lower probe falls about 40 %
|
|
13
|
+
faster than a mixed tank's, and its upper probe hardly moves. One UA
|
|
14
|
+
on the whole tank could not represent it, and the fitted UA was a
|
|
15
|
+
blend that cooled a mixed tank too fast, as after a cold season's full
|
|
16
|
+
recoveries. ``LossParams`` gains ``bottom_loss_btu_hr`` and
|
|
17
|
+
``bottom_gate_f``: heat leaving the lower zone, of which the lower
|
|
18
|
+
probe sees ``1 - exp(-gap / gate)`` (``sim.physics.tank.
|
|
19
|
+
bottom_loss_reach``). The standby walk (``decay.project_decay``) and
|
|
20
|
+
the recovery integrator charge it to the lower zone. A bottom loss of
|
|
21
|
+
0.0, the default and what stored parameter sets carry, reproduces the
|
|
22
|
+
model before it.
|
|
23
|
+
- ``sim.calibration.fit_loss`` fits the UA law and the bottom loss
|
|
24
|
+
together, through the standby walk, on the quiet windows opening with
|
|
25
|
+
a gap of 10 °F or less (``loss_windows``); ``fit_standby`` uses it.
|
|
26
|
+
On the installation above, the lower probe's median error over ten
|
|
27
|
+
hours fell from 1.25 to 0.77 °F from March to October and from 1.67
|
|
28
|
+
to 1.05 °F over the winter (1.15 °F trained without the winter).
|
|
29
|
+
``StandbyWindow`` carries each window's probes and air, and
|
|
30
|
+
``standby_ends`` and ``standby_error`` walk a loss over windows.
|
|
31
|
+
- The report has the bottom loss and its gate, and ``keep_better``
|
|
32
|
+
judges them with the standby loss, on the probes' error in each
|
|
33
|
+
held-out window's fall, °F/h.
|
|
34
|
+
|
|
35
|
+
Changed
|
|
36
|
+
-------
|
|
37
|
+
- The standby loss is fitted only on quiet windows opening with a gap of
|
|
38
|
+
10 °F or less: a wider gap is a draw's front closing, which the gap's
|
|
39
|
+
time constant describes.
|
|
40
|
+
- ``keep_better`` scores the standby group on the probes' error in each
|
|
41
|
+
held-out window's fall, walked as the simulation walks it, in place of
|
|
42
|
+
the error in log UA, so a loss with a bottom term and one without are
|
|
43
|
+
scored alike.
|
|
44
|
+
- The zone gap time constant is fitted with the bottom loss opening the
|
|
45
|
+
gaps it relaxes (``fit_gap_tau``'s ``loss``, ``gap_paths``), in turn
|
|
46
|
+
with the loss until it settles: a gap the bottom loss widens read as a
|
|
47
|
+
pure relaxation pushed the constant long. ``keep_better`` judges the
|
|
48
|
+
constant before the standby loss and fits and scores the loss on the
|
|
49
|
+
constant kept.
|
|
50
|
+
|
|
51
|
+
Version 9.8.0 (2026-10-21)
|
|
52
|
+
==========================
|
|
53
|
+
|
|
54
|
+
Added
|
|
55
|
+
-----
|
|
56
|
+
- **Refine a fit without making it worse** (``keep_better=True`` on
|
|
57
|
+
``sim_calibrate.calibrate`` and ``calibrate_changes``, #184). Each
|
|
58
|
+
group of terms holds out its latest evidence from its refit (the last
|
|
59
|
+
fifth, once it has 10 items) and keeps the existing values unless the
|
|
60
|
+
refit scores better there, by the error its own fit minimizes. The
|
|
61
|
+
terms in a group are kept or replaced together. ``Calibrated.judged``
|
|
62
|
+
records each judgement, and the report's reasons give both scores.
|
|
63
|
+
``sim_calibrate.score(done, params)`` scores any parameters on that
|
|
64
|
+
held-out evidence.
|
|
65
|
+
- ``sim.calibration.split_recoveries``, ``recovery_minutes``,
|
|
66
|
+
``power_cycles`` and ``cop_cycles``: the evidence the compressor and
|
|
67
|
+
power fits use, and their predictions, which ``fit_compressor``,
|
|
68
|
+
``fit_power_scale`` and ``fit_cop_scale`` now take from.
|
|
69
|
+
|
|
70
|
+
Fixed
|
|
71
|
+
-----
|
|
72
|
+
- **The report names compressor runs without an air temperature.**
|
|
73
|
+
A recovery is timed against the air, so a run with none (no air
|
|
74
|
+
given, and no heater ambient reading while the compressor runs) is
|
|
75
|
+
left out of the recoveries. The report blamed the heater instead:
|
|
76
|
+
"0 recoveries reached their target". ``Calibrated`` now counts the
|
|
77
|
+
runs (``n_runs``, ``n_runs_without_air``), and the compressor term's
|
|
78
|
+
reason and the notes say how many had no air
|
|
79
|
+
(``sim_calibrate.air_unread_note``).
|
|
80
|
+
- ``sim.calibration.with_standby`` quotes the fitted UA at the ΔT the
|
|
81
|
+
law was fitted at (50 °F). It kept the ``ua_ref_delta_t_f`` of the
|
|
82
|
+
parameters it was given, so a refit applied over parameters quoted at
|
|
83
|
+
another ΔT ran as a different loss law.
|
|
84
|
+
- ``sim.calibration.fit_cop_scale`` takes the integrator's COP on the
|
|
85
|
+
heater's own tank (``HeaterParams.tank``), as the simulation does. It
|
|
86
|
+
used the default tank's mass, so a heater with another tank was fitted
|
|
87
|
+
against a COP the simulation does not run.
|
|
88
|
+
|
|
5
89
|
Version 9.7.0 (2026-10-21)
|
|
6
90
|
==========================
|
|
7
91
|
|
|
@@ -78,7 +78,11 @@ zone (about half the tank's mass). Once the gap between the zones
|
|
|
78
78
|
closes, the tank heats as one body. In standby the gap relaxes on a
|
|
79
79
|
fitted time constant. Standby loss follows a jacket law,
|
|
80
80
|
``UA(dT) = ua_ref * (max(dT, 5) / 50) ^ n``, with the ambient as the
|
|
81
|
-
other side.
|
|
81
|
+
other side, on the whole tank. A bottom loss ``Q_b`` leaves the lower
|
|
82
|
+
zone alone: the lower probe sees the share ``1 - exp(-gap / gate)`` of
|
|
83
|
+
it, so a stratified tank's lower zone falls faster and its gap opens,
|
|
84
|
+
while a mixed tank hides it below the probe. With ``Q_b = 0`` the loss
|
|
85
|
+
is the jacket law alone.
|
|
82
86
|
|
|
83
87
|
**The elements.** They follow the device's own rules
|
|
84
88
|
(:doc:`heating-elements`): per-mode entry thresholds, a dead time,
|
|
@@ -139,16 +139,23 @@ fitted or kept the base's value, and why:
|
|
|
139
139
|
|
|
140
140
|
* - Term
|
|
141
141
|
- Fitted from
|
|
142
|
-
* - Standby loss and its
|
|
142
|
+
* - Standby loss, its exponent, the bottom loss and its gate
|
|
143
143
|
- Quiet windows of 3 h or more, starting 45 minutes after any
|
|
144
|
-
heating or hot water in use
|
|
145
|
-
|
|
146
|
-
the
|
|
147
|
-
|
|
144
|
+
heating or hot water in use, that open with a gap of 10 °F or
|
|
145
|
+
less between the probes. A window counts only if its fit tracks
|
|
146
|
+
the probes within 2 °F. Each window's upper and lower probe are
|
|
147
|
+
walked from its start as the simulation walks them, and the
|
|
148
|
+
terms are fitted to where the probes ended. The exponent is
|
|
149
|
+
fitted only when the windows span two 20 °F bands of tank-to-air
|
|
150
|
+
difference; it is held at 0 (a constant loss) otherwise. The
|
|
151
|
+
bottom loss needs 10 windows that open with a gap of 1 °F or
|
|
152
|
+
more; with fewer it is 0, and the loss is the jacket law
|
|
153
|
+
alone.
|
|
148
154
|
* - Zone gap time constant
|
|
149
155
|
- How fast the upper and lower probes' gap closes over quiet
|
|
150
156
|
windows; it needs 20 windows that open with a gap of 2 °F or
|
|
151
|
-
more.
|
|
157
|
+
more. The bottom loss opens the gaps it relaxes, so the two are
|
|
158
|
+
fitted in turn until the constant settles.
|
|
152
159
|
* - Compressor constant, evaporator approach
|
|
153
160
|
- Heat-pump recoveries that reached their target, against the loss
|
|
154
161
|
just fitted. The error is the mean absolute error of the
|
|
@@ -223,6 +230,48 @@ Assistant integration, can calibrate the same way:
|
|
|
223
230
|
4. Store ``params_to_document(done.calibration.params)``, and show the
|
|
224
231
|
``report(done)`` rows and ``done.notes``.
|
|
225
232
|
|
|
233
|
+
Refine an existing fit
|
|
234
|
+
----------------------
|
|
235
|
+
|
|
236
|
+
A fit made on months of history should not give way to one made on the
|
|
237
|
+
last ten days unless the new one predicts better. Pass the existing
|
|
238
|
+
fit as ``params`` with ``keep_better=True``:
|
|
239
|
+
|
|
240
|
+
.. code-block:: python
|
|
241
|
+
|
|
242
|
+
done = sim_calibrate.calibrate(
|
|
243
|
+
recorded(days), ambient=65.0, params=existing, keep_better=True
|
|
244
|
+
)
|
|
245
|
+
for j in done.judged:
|
|
246
|
+
print(j.group, j.kept, j.base_error, j.refit_error, j.why)
|
|
247
|
+
|
|
248
|
+
Each group of terms holds out its latest evidence from its refit:
|
|
249
|
+
|
|
250
|
+
- the standby loss, its exponent, the bottom loss and its gate: its
|
|
251
|
+
quiet windows, scored on the probes' error in each window's fall,
|
|
252
|
+
°F/h;
|
|
253
|
+
- the zone gap time constant: its windows that open a gap, judged
|
|
254
|
+
before the standby loss, which is then fitted and scored on the
|
|
255
|
+
constant kept;
|
|
256
|
+
- the compressor constant and the evaporator approach: its reached
|
|
257
|
+
recoveries;
|
|
258
|
+
- the power scale: the metered compressor cycles it can use;
|
|
259
|
+
- the COP terms: the cycles the COP fit can use (without a meter of
|
|
260
|
+
draws, those no water was drawn around).
|
|
261
|
+
|
|
262
|
+
Once a group has 10 items, the latest fifth (at least 2) is held out.
|
|
263
|
+
The refit replaces the existing values only where it scores better on
|
|
264
|
+
them, by the error its own fit minimizes. With fewer items the existing
|
|
265
|
+
values stay. The terms in a group are kept or replaced together, and the
|
|
266
|
+
report's reasons say which, with both scores.
|
|
267
|
+
``sim_calibrate.score(done, params)`` gives those errors for any
|
|
268
|
+
parameters.
|
|
269
|
+
|
|
270
|
+
Use it over a fit of this heater. The defaults are another heater's fit,
|
|
271
|
+
and ``keep_better`` keeps them wherever there is too little evidence to
|
|
272
|
+
judge by. A group the existing fit lists as unfitted takes its refit, as
|
|
273
|
+
without ``keep_better``.
|
|
274
|
+
|
|
226
275
|
``sim.calibration.calibrate`` underneath takes the frame
|
|
227
276
|
``sim_adapters.history`` builds; ``sim_adapters.add_inputs`` adds the
|
|
228
277
|
air, the humidity, a meter's draws and the circulation's runs to it.
|
|
@@ -294,6 +343,12 @@ leave out what your installation does not record. ``read_heater_history``:
|
|
|
294
343
|
- notes a value it could not read, and an entity whose history starts
|
|
295
344
|
after ``start``.
|
|
296
345
|
|
|
346
|
+
A recovery is timed against the air, so the compressor and power fits
|
|
347
|
+
need an air temperature over each compressor run: the air beside the
|
|
348
|
+
heater (``record=``, ``air`` or ``ambient``), or the heater's own reading
|
|
349
|
+
(``ambient`` in ``HeaterEntities``). Runs without one are no recovery,
|
|
350
|
+
and the report says how many there were.
|
|
351
|
+
|
|
297
352
|
Give ``anti_legionella`` where it is recorded. Without it an
|
|
298
353
|
anti-legionella cycle is not kept out of the recoveries, and the notes
|
|
299
354
|
say so.
|
|
@@ -150,7 +150,8 @@ Hot water and the heat book
|
|
|
150
150
|
|
|
151
151
|
.. automodule:: nwp500.sim.calibration
|
|
152
152
|
:members: calibrate, Calibration, fit_standby, StandbyFit, StandbyWindow,
|
|
153
|
-
fit_compressor, CompressorFit,
|
|
153
|
+
fit_compressor, CompressorFit, split_recoveries, recovery_minutes,
|
|
154
|
+
clean_draws, CleanDraw, crossing,
|
|
154
155
|
demonstrated, frontier, capacity, held_out, fit_evidence,
|
|
155
156
|
EvidenceFit, cold_lower_cap, RecordedBook, fit_book_terms, BookFit,
|
|
156
157
|
book_error_bands, book_error_btu, empty_point,
|
|
@@ -163,11 +164,13 @@ Hot water and the heat book
|
|
|
163
164
|
element_off_points, element_power, element_grid, element_runs,
|
|
164
165
|
fit_element_rates, ElementRateFit, day_ci,
|
|
165
166
|
energy_saver_off_deficit, upper_start_edge, fit_power,
|
|
166
|
-
PowerFit, fit_power_scale,
|
|
167
|
+
PowerFit, fit_power_scale, power_cycles, cop_cycles, CopCycle,
|
|
167
168
|
fit_cop_scale, solve_cop_fit, solve_cop_scale, draw_free_withdrawn,
|
|
168
169
|
metered_withdrawn, metered_lead,
|
|
169
170
|
path_to_end, with_power, snapshots, recoveries, quiet_windows,
|
|
170
171
|
busy_intervals, fit_window, fit_ua_law, fit_gap_tau, with_standby,
|
|
172
|
+
fit_loss, LossFit, loss_windows, standby_ends, standby_error,
|
|
173
|
+
walk_tau, gap_paths, gap_error,
|
|
171
174
|
with_compressor, UA_SEARCH_BOUNDS, UA_EXPONENT_BOUNDS, DRAW_LEAD
|
|
172
175
|
|
|
173
176
|
.. automodule:: nwp500.sim.profile
|
|
@@ -249,7 +252,7 @@ The pieces the entry points are built from.
|
|
|
249
252
|
vapor_enthalpy, dew_point_f
|
|
250
253
|
|
|
251
254
|
.. automodule:: nwp500.sim.physics.tank
|
|
252
|
-
:members: ua_at
|
|
255
|
+
:members: ua_at, bottom_loss_reach, bottom_loss_drop_f
|
|
253
256
|
|
|
254
257
|
.. automodule:: nwp500.sim.physics.element
|
|
255
258
|
:members: mode_recovery, ModeRecovery, mode_plan, ModePlan,
|
|
@@ -299,6 +302,7 @@ Recorded history
|
|
|
299
302
|
|
|
300
303
|
.. automodule:: nwp500.sim_calibrate
|
|
301
304
|
:members: calibrate, calibrate_changes, Calibrated, report, Term, max_gap,
|
|
305
|
+
score, Judged, HeldOut, GROUPS, air_unread_note,
|
|
302
306
|
CalibrationInputError, DEFAULT_HUMIDITY_PCT, GAP_SAMPLES, MIN_GAP,
|
|
303
307
|
DEFAULT_BASE_NOTE, NO_AIR_NOTE
|
|
304
308
|
|
|
@@ -78,7 +78,7 @@ from nwp500.sim.inputs import (
|
|
|
78
78
|
Schedules,
|
|
79
79
|
Settings,
|
|
80
80
|
)
|
|
81
|
-
from nwp500.sim.params import HeaterParams
|
|
81
|
+
from nwp500.sim.params import TAU_GAP_PRIOR_H, HeaterParams
|
|
82
82
|
from nwp500.sim.physics.compressor import MAX_MINUTES, predict_physics_detailed
|
|
83
83
|
from nwp500.sim.physics.element import (
|
|
84
84
|
DEVICE_MODE,
|
|
@@ -224,10 +224,6 @@ LOW_CONFIDENCE_FLOOR = 0.6
|
|
|
224
224
|
#: start was never searched (the TOU-opening start still was), so an
|
|
225
225
|
#: answer may miss a start the heater makes.
|
|
226
226
|
HP_LOWER_ON_UNKNOWN = "hp_lower_on_unknown"
|
|
227
|
-
#: The gap time constant served when the parameters carry none
|
|
228
|
-
#: (``TankParams.stratification_gap_tau_h``), h: history puts it near
|
|
229
|
-
#: 60 h on this product.
|
|
230
|
-
TAU_GAP_PRIOR_H = 60.0
|
|
231
227
|
#: Draws opened a gap that closes on that prior, not a fitted constant:
|
|
232
228
|
#: under no draws it only shapes how an existing gap closes.
|
|
233
229
|
TAU_GAP_PRIOR = "tau_gap_prior"
|