7.8 KiB
Story 11.15: Bitzer Parser
Status: done
Story
As a refrigeration engineer, I want Bitzer compressor data integration, so that I can use Bitzer coefficients in simulations.
Acceptance Criteria
-
Given a
BitzerBackendstruct When constructed viaBitzerBackend::new()Then it discovers compressor models from CSV files indata/bitzer/compressors/(e.g. by scanning*.csvor loading an index) And eagerly pre-caches all discovered models into memory -
Given a valid Bitzer CSV file (Bitzer polynomial format) When parsed by
BitzerBackendThen it yields aCompressorCoefficientsstruct with 10 capacity and 10 power coefficients compatible with AHRI 540 And Bitzer polynomial format is mapped to the standard polynomial form (Ts, Td, Ts², Ts·Td, Td², …) -
Given
BitzerBackendimplementsVendorBackendWhen I calllist_compressor_models()Then it returns all model names from the pre-loaded cache in sorted order -
Given a valid model name (e.g. file stem of a CSV) When I call
get_compressor_coefficients("4NFC-20Y")Then it returns the fullCompressorCoefficientsstruct -
Given a model name not in the catalog When I call
get_compressor_coefficients("NONEXISTENT")Then it returnsVendorError::ModelNotFound("NONEXISTENT") -
Given
list_bphx_models()called onBitzerBackendWhen Bitzer only provides compressor data here Then it returnsOk(vec![])(empty list, not an error) -
Given
get_bphx_parameters("anything")called onBitzerBackendWhen Bitzer only provides compressor data here Then it returnsVendorError::InvalidFormatwith a descriptive message -
Given unit tests When
cargo test -p entropyk-vendorsis run Then all existing tests still pass And new Bitzer-specific tests pass (CSV loading, format mapping, error cases)
Tasks / Subtasks
- Task 1: Define Bitzer CSV format and sample data (AC: 2)
- Subtask 1.1: Document or adopt Bitzer polynomial CSV layout (columns for capacity/power coefficients, validity range)
- Subtask 1.2: Create
data/bitzer/compressors/and at least one sample CSV (e.g.4NFC-20Y.csvor equivalent) - Subtask 1.3: If using an index, add
index.jsonorindex.csvlisting model names
- Task 2: Implement
BitzerBackend(AC: 1, 3, 4, 5, 6, 7)- Subtask 2.1: Create
src/compressors/bitzer.rswithBitzerBackendstruct - Subtask 2.2: Implement
BitzerBackend::new()resolving data path viaENTROPYK_DATAwith fallback toCARGO_MANIFEST_DIR/data - Subtask 2.3: Implement CSV discovery (glob
*.csvindata/bitzer/compressors/and use file stem as model id, or load from index) and pre-cache - Subtask 2.4: Implement CSV parsing: Bitzer polynomial format →
CompressorCoefficients(andCompressorValidityRange) - Subtask 2.5: Implement
VendorBackendforBitzerBackend(list_compressor_models sorted, get_compressor_coefficients, list_bphx_models empty, get_bphx_parameters InvalidFormat)
- Subtask 2.1: Create
- Task 3: Wire up module exports
- Subtask 3.1: Add
pub mod bitzer;insrc/compressors/mod.rs(uncomment or add) - Subtask 3.2: Re-export
BitzerBackendinsrc/lib.rs
- Subtask 3.1: Add
- Task 4: Write unit tests (AC: 8)
- Subtask 4.1: Test
BitzerBackend::new()(orfrom_path) successfully constructs - Subtask 4.2: Test
list_compressor_models()returns sorted models - Subtask 4.3: Test
get_compressor_coefficients()returns valid data for a known CSV - Subtask 4.4: Test
ModelNotFoundfor unknown model - Subtask 4.5: Test
list_bphx_models()returns empty - Subtask 4.6: Test
get_bphx_parameters()returnsInvalidFormat
- Subtask 4.1: Test
- Task 5: Verify build and tests (AC: 8)
- Subtask 5.1: Run
cargo test -p entropyk-vendors - Subtask 5.2: Run
cargo clippy -p entropyk-vendors -- -D warnings
- Subtask 5.1: Run
Dev Notes
- Bitzer supplies compressor data in CSV format with a proprietary polynomial layout; the implementation must map this to the existing
CompressorCoefficientsandCompressorValidityRangetypes invendor_api.rs. - Reuse the same data-path resolution and error-handling patterns as
DanfossBackendandCopelandBackend:ENTROPYK_DATA, path sanitization (reject model names containing/,\, or..),log::warn!for skipped files, and structuredVendorError(e.g.IoError { path, source },InvalidFormat(message)). - Keep
list_compressor_models()deterministic by maintaining a sorted list of model names (e.g.sorted_models: Vec<String>populated and sorted after loading).
Project Structure Notes
- Alignment with existing vendors layout:
crates/vendors/data/bitzer/compressors/for CSV files (and optional index).crates/vendors/src/compressors/bitzer.rsforBitzerBackend; export incompressors/mod.rsandlib.rs.
References
- Source: epics.md – Story 11.15
- Source: epic-11-technical-specifications.md – Story 11.11–15
- Source: vendor_api.rs –
CompressorCoefficients,CompressorValidityRange,VendorBackend - Source: danfoss.rs – data path resolution, pre-cache, sorted models, path sanitization, error reporting
- Source: 11-14-danfoss-parser.md – previous story patterns and completion notes
Dev Agent Record
Agent Model Used
Cursor / Auto (dev-story workflow)
Debug Log References
Completion Notes List
- Task 1: Defined Bitzer CSV format with header row (model, manufacturer, refrigerant, c0..c9, p0..p9, t_suction_min/max, t_discharge_min/max). Created
data/bitzer/compressors/4NFC-20Y.csvand4HES-5Y.csv. Discovery by glob*.csv(no index file). - Task 2: Implemented
BitzerBackendinsrc/compressors/bitzer.rswithnew(),from_path(),load_compressors()(dir scan),load_model()andparse_bitzer_csv(). Path resolution viaENTROPYK_DATA/CARGO_MANIFEST_DIR/data. Path sanitization andlog::warn!for skipped files.VendorBackendimpl:list_compressor_models(sorted),get_compressor_coefficients,list_bphx_modelsempty,get_bphx_parameters/compute_uareturnInvalidFormat. - Task 3: Added
pub mod bitzerincompressors/mod.rsand re-exportedBitzerBackendinlib.rs. - Task 4: Added 11 unit tests in
bitzer.rs(new, from_path, vendor_name, list_compressor_models, get_compressor 4NFC-20Y/4HES-5Y, validity_range, model_not_found, list_bphx_empty, get_bphx_error, object_safety). - Task 5:
cargo test -p entropyk-vendors(65 tests passed),cargo clippy -p entropyk-vendors -- -D warnings(fixed unnecessary_map_or → is_some_and). Addedcsv = "1.3"to Cargo.toml. - Code review (AI): Addressed MEDIUM/LOW findings: documented AHRI 540 column order (c0..c9, p0..p9 = Ts, Td, Ts², Ts·Td, Td², Ts³, Td·Ts², Ts·Td², Td³) in bitzer.rs module and parse_bitzer_csv doc; documented single-data-row behaviour (first row used, extra rows ignored) and added test test_bitzer_csv_multiple_rows_first_used; updated compressors/mod.rs comment (Danfoss 11.14, Bitzer 11.15).
File List
- crates/vendors/Cargo.toml (modified – added csv dependency)
- crates/vendors/data/bitzer/compressors/4NFC-20Y.csv (created)
- crates/vendors/data/bitzer/compressors/4HES-5Y.csv (created)
- crates/vendors/src/compressors/bitzer.rs (created, then modified – code review: AHRI 540 doc, single-row doc, test)
- crates/vendors/src/compressors/mod.rs (modified – pub mod bitzer; then code review: comment update)
- crates/vendors/src/lib.rs (modified – re-export BitzerBackend)