diff --git a/docs/cable-sizing-module.md b/docs/cable-sizing-module.md index 26e8c47..80b7cc8 100644 --- a/docs/cable-sizing-module.md +++ b/docs/cable-sizing-module.md @@ -76,14 +76,50 @@ cell, nothing crashes, no data is affected, and the rest of the app (including manual cable-field editing) is completely unaffected - the module's actual logic and persistence never depend on this column key. -## How a suggestion is applied +## Feature overview -The module never writes to `circuits` directly. The modal's "Empfehlung -übernehmen" button calls the **existing, unmodified** frontend helper: +- **Calculate a recommendation**: laying method, insulation, conductor + material, ambient temperature, grouping, cos phi and max voltage drop - + same VDE 0298-4 reference-method model as the sibling Kabelliste tool + (see Verification status below). +- **Breaker-aware sizing**: if the circuit already has a protection device + (`circuit.protectionDevice`), the cross-section is selected against + `designCurrentA = max(operatingCurrentA, protectionDevice.ratedCurrentA)`, + not the load current alone - the standard `In <= Iz` rule (a breaker only + trips at its own rated current, so a cable sized for the actual load + alone could overheat under sustained current below that threshold). If no + cross-section can cover an oversized breaker, that is reported as the + limiting factor by name, not a generic capacity error. +- **Maximum length for the voltage-drop limit**: each cross-section option + also reports the longest single run that still meets the requested + `maxVoltageDropPercent` at the given load - the inverse of the + voltage-drop check, shown for the recommended cross-section. +- **Practical minimum for socket circuits**: `single_phase`-category + circuits are raised to at least 2.5 mm² if the calculation alone would + recommend less - see the dedicated note under Verification status. Never + lowers a calculation that already needs more. +- **Manual entry, always available**: the modal has a plain text Kabeltyp/ + Querschnitt field. Running a calculation pre-fills it as a suggestion, + but the field is the single source of truth for what gets applied, and + stays freely editable - satisfying + `docs/spec/06-future-sizing-and-calculations.md`'s explicit requirement + that "users must remain able to manually override suggestions" without + requiring a calculation to have been run first. A non-blocking warning + appears if the typed value is not a standard cross-section, is smaller + than the last calculation, or is below the practical minimum above - + informational only, never forced, matching the same spec doc's "shown as + a warning or status indicator, not as an automatic forced change." + +## How a suggestion or manual entry is applied + +The module never writes to `circuits` directly. The modal's "Übernehmen" +button calls the **existing, unmodified** frontend helper with whatever is +currently in the Kabeltyp/Querschnitt fields, calculated or hand-typed: ```ts updateCircuitById(projectId, expectedRevision, circuitId, { cableCrossSection: "4 mm²", + cableType: "NYM-J 3x2.5", cableLength: 30, }); ``` @@ -94,10 +130,8 @@ cell edits. This means: - optimistic concurrency (`expectedRevision`) is respected automatically - the change appears in the project's revision history and is undoable/ redoable exactly like a manual edit -- manually typing a value into the `cableCrossSection` cell keeps working - unchanged - the module only adds a small calculator trigger next to the - cell, per `docs/spec/06-future-sizing-and-calculations.md`'s explicit - requirement that "users must remain able to manually override suggestions" +- nothing is ever written automatically - calculating only fills the modal's + own fields, applying is always an explicit, separate click ## API contract @@ -119,6 +153,8 @@ cell edits. This means: "maxVoltageDropPercent": 3, "harmonicNeutralLoad": "none", // "none" | "15to33Percent" | "over33Percent", three-phase only "existingProtectionRatedCurrentA": 16, // optional, from circuit.protectionDevice + "circuitCategory": "single_phase", // optional, from the circuit's section.category - + // enables the practical-minimum convention below "context": { "projectId": "...", "circuitId": "...", "equipmentIdentifier": "-1F1.1" } } ``` @@ -149,6 +185,15 @@ recommended cross-section's corrected capacity) is a **simplified** `In <= Iz` check only - it is not a full IEC 60364-4-43 overload (`I2 <= 1.45 x Iz`) or short-circuit withstand check. +`PRACTICAL_MINIMUM_CROSS_SECTION_MM2` (2.5 mm² for `single_phase`) is +**not** a verified norm value at all - it is a named planning convention, +sourced directly from this project's own +`docs/spec/06-future-sizing-and-calculations.md` ("Standard Single-Phase +Circuits ... usually use ... cable cross-section: 2.5 mm²"), applied as a +floor on top of the calculated recommendation. It intentionally only +covers the one category and one convention that document already states; +it is not a general substitute for norm-compliant calculation. + ## Relationship to the project's own future-sizing spec `docs/spec/06-future-sizing-and-calculations.md` separately describes simple @@ -177,8 +222,22 @@ app for now", per the intent of this proposal. ## Local testing -Deployed and manually exercised on an internal test host at -`http://192.168.0.133:3220` (a fork of this repository's `main` branch, not -pushed anywhere). `npm test`, `npm run build:api`, `npm run build:web` and -`npm run typecheck:scripts` all pass with this module included; see the -accompanying diff/branch for the exact commit. +Deployed and manually exercised end-to-end on an internal test host at +`http://192.168.0.133:3220` (own docker deployment, own subnet/ports to +avoid clashing with ~50 other containers on that host - see the two +commits marked "Local-only" in this branch, which are not part of this +proposal and should not be carried over if it is ever proposed upstream). +Exercised against seeded real project/circuit data created through the +actual command API (not direct DB writes), including a deliberately long +(85 m) circuit to trigger the voltage-drop-critical path. + +`npm test`, `npm run build:api`, `npm run build:web` and +`npm run typecheck:scripts` all pass with this module included at every +commit in this branch. + +This branch (`feature/cable-sizing-module`) is pushed to a mirror of this +repository under this homelab's own Forgejo instance, not to +`git.jappel.io` - no write access to the upstream repository was available +or used. See the branch's commit history for the incremental history of +this module, including fixes made during manual testing (trigger column, +icon rendering, breaker-aware sizing).