Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 0 additions & 7 deletions CanKit.Pro.sln
Original file line number Diff line number Diff line change
Expand Up @@ -38,8 +38,6 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "CanKit.Pro.Addressing", "sr
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "CanKit.Pro.CANopen", "src\CanKit.Pro.CANopen\CanKit.Pro.CANopen.csproj", "{40B6A67F-A5F7-5F9B-BE82-D6573563021F}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "CanKit.Pro.Hawe", "src\CanKit.Pro.Hawe\CanKit.Pro.Hawe.csproj", "{B8C4D4AA-1C87-50EA-ADB6-6D511D416E1E}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "CanKit.Pro.IsoTp", "src\CanKit.Pro.IsoTp\CanKit.Pro.IsoTp.csproj", "{24D148F4-45F3-5E3E-83E6-05FD963051FB}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "CanKit.Pro.J1939", "src\CanKit.Pro.J1939\CanKit.Pro.J1939.csproj", "{2CFA3474-2C5F-56A0-963E-7A16D9FF21A5}"
Expand Down Expand Up @@ -84,10 +82,6 @@ Global
{40B6A67F-A5F7-5F9B-BE82-D6573563021F}.Debug|Any CPU.Build.0 = Debug|Any CPU
{40B6A67F-A5F7-5F9B-BE82-D6573563021F}.Release|Any CPU.ActiveCfg = Release|Any CPU
{40B6A67F-A5F7-5F9B-BE82-D6573563021F}.Release|Any CPU.Build.0 = Release|Any CPU
{B8C4D4AA-1C87-50EA-ADB6-6D511D416E1E}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{B8C4D4AA-1C87-50EA-ADB6-6D511D416E1E}.Debug|Any CPU.Build.0 = Debug|Any CPU
{B8C4D4AA-1C87-50EA-ADB6-6D511D416E1E}.Release|Any CPU.ActiveCfg = Release|Any CPU
{B8C4D4AA-1C87-50EA-ADB6-6D511D416E1E}.Release|Any CPU.Build.0 = Release|Any CPU
{24D148F4-45F3-5E3E-83E6-05FD963051FB}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{24D148F4-45F3-5E3E-83E6-05FD963051FB}.Debug|Any CPU.Build.0 = Debug|Any CPU
{24D148F4-45F3-5E3E-83E6-05FD963051FB}.Release|Any CPU.ActiveCfg = Release|Any CPU
Expand Down Expand Up @@ -148,7 +142,6 @@ Global
{EE488B24-01E3-5C1E-B2AF-BB0A9255C5F0} = {5368F703-B5EE-5524-8E24-C0CAA76683E4}
{521A33A4-20B4-5353-ABCF-8C7F092AE769} = {5368F703-B5EE-5524-8E24-C0CAA76683E4}
{40B6A67F-A5F7-5F9B-BE82-D6573563021F} = {5368F703-B5EE-5524-8E24-C0CAA76683E4}
{B8C4D4AA-1C87-50EA-ADB6-6D511D416E1E} = {5368F703-B5EE-5524-8E24-C0CAA76683E4}
{24D148F4-45F3-5E3E-83E6-05FD963051FB} = {5368F703-B5EE-5524-8E24-C0CAA76683E4}
{2CFA3474-2C5F-56A0-963E-7A16D9FF21A5} = {5368F703-B5EE-5524-8E24-C0CAA76683E4}
{0281D090-907B-5820-8CB7-CDE83B209501} = {5368F703-B5EE-5524-8E24-C0CAA76683E4}
Expand Down
11 changes: 5 additions & 6 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,9 @@ needs and that people otherwise rebuild, slightly differently and slightly wrong

## Packages

**L2 — the raw-CAN service layer.** Published to nuget.org, versioned and released together.
Published to nuget.org, versioned and released together.

**L2 — the raw-CAN service layer.**

| Package | What it gives you | Depends on |
| --- | --- | --- |
Expand All @@ -30,9 +32,7 @@ needs and that people otherwise rebuild, slightly differently and slightly wrong
| [`CanKit.Pro.Addressing`](src/CanKit.Pro.Addressing) | Validated 11/29-bit CAN IDs, J1939 PGN/priority/PDU/source-address composition, J1939 NAME and PGN catalogues. | — |
| [`CanKit.Pro.Reliability`](src/CanKit.Pro.Reliability) | Deadlines whose expiry is guaranteed to be checked, and a `BusStateMonitor` that pushes `ErrWarning`/`ErrPassive`/`BusOff` transitions and recovery. | `CanKit.Abstractions`, `CanKit.Pro.Actor` |

**L3/L4 — transports and application protocols.** Built and tested on every CI run, **not yet
published**: the APIs are still settling, and shipping them now would freeze decisions that
should stay open. Reference the projects from a clone until they are ready.
**L3/L4 — transports and application protocols.**

| Package | What it gives you |
| --- | --- |
Expand All @@ -41,9 +41,8 @@ should stay open. Reference the projects from a clone until they are ready.
| [`CanKit.Pro.CANopen`](src/CanKit.Pro.CANopen) | CiA 301: SDO client/server incl. block transfer, static and dynamic PDO mapping, NMT, heartbeat and node guarding, EMCY, object dictionary. |
| [`CanKit.Pro.J1939`](src/CanKit.Pro.J1939) | J1939 node: address claim with arbitrary-address fallback, fixed-rate periodic send, SPN catalogue over J1939-71. |
| [`CanKit.Pro.Uds`](src/CanKit.Pro.Uds) | ISO 14229-1 client over ISO-TP: session control, security access, read/write by identifier, routine control, upload/download, P2/P2\* timing and 0x78 response-pending. |
| [`CanKit.Pro.Hawe`](src/CanKit.Pro.Hawe) | Framework for the HAWE private protocol: codec registry and typed message dispatch. |

Everything targets `netstandard2.0` and `net8.0`.
Everything targets `netstandard2.0` and `net10.0`.

## Install

Expand Down
15 changes: 6 additions & 9 deletions docs/architecture/arc42-CanKit.Pro.md
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@
> voraussetzen, nicht durchsetzen (siehe Abschnitt 11).
>
> Requirement-IDs verweisen auf das SRS (`docs/requirements/SRS-CanKit.Pro.md`); Schema:
> `FR-RAW-*`, `FR-TP-*`, `FR-UDS-*`, `FR-CO-*`, `FR-J1939-*`, `FR-HAWE-*`, `NFR-*`, `CON-*`. Die
> `FR-RAW-*`, `FR-TP-*`, `FR-UDS-*`, `FR-CO-*`, `FR-J1939-*`, `NFR-*`, `CON-*`. Die
> technischen Schulden in Abschnitt 11 sind aus dem Deep-Code-Review
> (`docs/reviews/2026-07-14-deep-code-review.md`) abgeleitet; dessen Abschnittsnummern werden als
> „Review §x.y" referenziert.
Expand All @@ -50,7 +50,7 @@ Diese Nomenklatur ist identisch zur SRS und wird im gesamten Dokument verwendet:
| **L1** | Raw-CAN-Kern | vorhanden | `ICanBus`, `CanFrame`, Registry, Utilities, Diagnostics |
| **L2** | Raw-CAN-Dienstebene | **NEU / Ziel** | Multi-Consumer-Demux, Ownership-Vertrag, TX-Confirm, Adressierung, Aktor-Modell, Fehler-/Timeout-Infrastruktur |
| **L3** | Transport-Ebene | Prototyp (ISO-TP) / Ziel (J1939-TP) | ISO-TP (ISO 15765-2), J1939-TP (BAM/CM) |
| **L4** | Anwendungsprotokoll-Ebene | **NEU / Ziel** | UDS, CANopen, J1939-App, HAWE-Privatprotokoll |
| **L4** | Anwendungsprotokoll-Ebene | **NEU / Ziel** | UDS, CANopen, J1939-App |

### Auflösung der Requirement-Referenzen (arc42 ↔ SRS)

Expand Down Expand Up @@ -85,7 +85,7 @@ CanKit ist eine **herstellerneutrale .NET-Bibliothek für den CAN-Bus** (Classic
und CAN FD). Sie kapselt heterogene Vendor-Treiber (SocketCAN, ZLG, PCAN, Kvaser,
Vector, ControlCAN) hinter einer einheitlichen API (`ICanBus`) und stellt darüber
hinaus eine Erweiterungsplattform (SPI + Registry) bereit, auf der Transport- und
Anwendungsprotokolle (ISO-TP, UDS, J1939, CANopen, HAWE) aufsetzen können.
Anwendungsprotokolle (ISO-TP, UDS, J1939, CANopen) aufsetzen können.

Kernanliegen:

Expand Down Expand Up @@ -119,7 +119,7 @@ Zero-Copy) erhöhen den Aufwand für Q4 und für einen sicheren **Frame-Ownershi
|-------|------------------------------|
| **Anwendungsentwickler** (Diagnose/Steuerung) | Stabile, hardwareunabhängige API; einfache Endpoint-Öffnung; async-Streaming. |
| **Adapter-Autor** (Vendor-Integration) | Klares Adapter-Muster (Bus/Transceiver/Options/Native), SPI-Verträge, Fake-Schicht als Vorlage. |
| **Protokoll-Autor** (ISO-TP/UDS/J1939/CANopen/HAWE) | Verbindlicher Ownership-Vertrag, Multi-Consumer-Demux, TX-Confirm, definiertes Threading-Modell (→ L2). |
| **Protokoll-Autor** (ISO-TP/UDS/J1939/CANopen) | Verbindlicher Ownership-Vertrag, Multi-Consumer-Demux, TX-Confirm, definiertes Threading-Modell (→ L2). |
| **Maintainer / Architekt** | Geringe Kopplung, testbare Kerne, dokumentierte Entscheidungen (ADRs), Kontrolle über Release-Reife. |
| **CI/Release-Engineer** | Adapterweise Pfadfilter, `-c Fake`-Builds, NuGet-Packaging, reproduzierbare Matrix. |
| **Endnutzer/Betreiber** | Zuverlässiges Verhalten unter Last, kein Ressourcenleck über lange Laufzeiten. |
Expand Down Expand Up @@ -181,7 +181,7 @@ flowchart TB
subgraph App["Anwendungsprozess (.NET)"]
UserApp["Anwendungscode<br/>Diagnose / Steuerung / Telemetrie"]
subgraph CanKitLib["CanKit (Bibliothek, in-process)"]
L4["L4 Anwendungsprotokolle<br/>UDS / CANopen / J1939 / HAWE (NEU)"]
L4["L4 Anwendungsprotokolle<br/>UDS / CANopen / J1939 (NEU)"]
L3["L3 Transport<br/>ISO-TP (Prototyp) / J1939-TP (Ziel)"]
L2["L2 Raw-CAN-Dienste<br/>Demux / Ownership / TX-Confirm (NEU)"]
L1["L1 Raw-CAN-Kern<br/>ICanBus / CanFrame / Registry"]
Expand Down Expand Up @@ -254,7 +254,6 @@ flowchart TB
UDS["UDS (ISO 14229)"]
CANopen["CANopen (SDO/PDO/NMT/EMCY)"]
J1939App["J1939 (Applikation)"]
HAWE["HAWE-Privatprotokoll"]
end

subgraph L3["L3 Transport"]
Expand Down Expand Up @@ -293,7 +292,6 @@ flowchart TB
UDS --> IsoTp
CANopen --> Demux
J1939App --> J1939Tp
HAWE --> Demux
IsoTp --> Demux
J1939Tp --> Demux
Demux --> ICanBus
Expand Down Expand Up @@ -322,7 +320,7 @@ flowchart TB
| L1 Raw-CAN-Kern | vorhanden | Herstellerneutraler Frame-Zugriff, Discovery, Utilities, Diagnostics. | `ICanBus`, `CanBus.Open`, `CanRegistry` | `FR-RAW-*` |
| L2 Raw-CAN-Dienste | NEU | Ein RX-Strom → N unabhängige gefilterte Consumer; Ownership-Vertrag; TX-Confirm; Aktor-Modell. | (neu) `ICanBusService` / `ISubscription` | `FR-RAW-DEMUX-*`, `FR-RAW-OWN-*`, `FR-RAW-TXC-*` |
| L3 Transport | Prototyp/Ziel | Segmentierung/Reassemblierung (ISO-TP), Sessions (J1939-TP). | `IIsoTpChannel`, `IIsoTpScheduler` | `FR-TP-*` |
| L4 Anwendungsprotokolle | NEU | Diagnose-/Applikationssemantik auf L3/L2. | (neu) protokollspezifisch | `FR-UDS-*`, `FR-CO-*`, `FR-J1939-*`, `FR-HAWE-*` |
| L4 Anwendungsprotokolle | NEU | Diagnose-/Applikationssemantik auf L3/L2. | (neu) protokollspezifisch | `FR-UDS-*`, `FR-CO-*`, `FR-J1939-*` |

## 5.2 Ebene 2 – Zoom L1 (Raw-CAN-Kern, vorhanden)

Expand Down Expand Up @@ -1308,7 +1306,6 @@ Ziel-Architektur und Voraussetzung für belastbare L3/L4-Stacks.
| **CANopen** | Höheres Protokoll (CiA 301) auf CAN. |
| **SDO / PDO** | Service / Process Data Object (CANopen). |
| **NMT / EMCY** | Network Management / Emergency Object (CANopen). |
| **HAWE** | Hier: herstellerspezifisches Privatprotokoll (Ziel-L4). |
| **SPI (hier)** | Service Provider Interface; interne Erweiterungspunkte (`CanKit.Abstractions.SPI.*`), nicht der Hardware-SPI-Bus. |
| **Fake-Native** | `*.Fake.cs`-Spiegel der P/Invoke-Schicht für hardwarelose Builds (`-c Fake`). |
| **Virtual-Hub** | In-Memory-Loopback-Adapter (`VirtualBusHub`) für Tests. |
Expand Down
18 changes: 13 additions & 5 deletions docs/migration-from-legacy.md
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ four L2 packages, while the entire transport and application stack is on `develo
| --- | --- |
| `src/core/CanKit.Pro.{Actor,Addressing,RawCan,Reliability}/` | → `src/CanKit.Pro.*/` — **source unchanged** apart from comments referring to fork-internal files |
| `src/transports/CanKit.Pro.{IsoTp,J1939Tp}/` | → `src/CanKit.Pro.*/` |
| `src/protocols/CanKit.Pro.{CANopen,J1939,Uds,Hawe}/` | → `src/CanKit.Pro.*/` |
| `src/protocols/CanKit.Pro.{CANopen,J1939,Uds}/` | → `src/CanKit.Pro.*/` |
| The Pro test suites in `tests/CanKit.Tests/TestCases/` | → `tests/CanKit.Pro.Tests/TestCases/`, adapted (below) |
| The five Pro quickstart samples | → `samples/CanKit.Pro.Sample.*/` |
| `docs/architecture/`, `docs/requirements/`, `docs/reviews/` | → `docs/`, with headers that mark CanKit as external context |
Expand All @@ -47,12 +47,20 @@ The flat `src/CanKit.Pro.<Name>/` layout replaces the legacy `core/transports/pr
a repository whose every project is a `CanKit.Pro.*` package, the extra directory level encoded a
layer that the package name already states.

`CanKit.Pro.Hawe` (the generic extension framework for a customer's confidential private
protocol) moved over with everything else initially, but was later removed from this public
repository entirely and continues as a separate, internal-only repo — its presence here was never
more than the generic SPI extension point, and even that is confidential enough not to belong in
a public source history.

### Publishing

Only the four L2 packages publish. `CanKit.Pro.{IsoTp,J1939Tp,CANopen,J1939,Uds,Hawe}` keep
`IsPackable=false`, which is the legacy repository's own assessment (`publish: false` in its
`eng/packages.json`) — they are pre-release, and this migration is not the moment to overrule
that. They are still built and tested on every CI run, so they cannot rot silently.
All `CanKit.Pro.*` packages built from this repo publish to nuget.org. The four L2 packages
(`Actor`, `Addressing`, `RawCan`, `Reliability`) were first; `CanKit.Pro.{IsoTp,J1939Tp,CANopen,
J1939,Uds}` initially kept `IsPackable=false` — the legacy repository's own assessment
(`publish: false` in its `eng/packages.json`), since they were pre-release and this migration was
not the moment to overrule that — until their APIs settled enough to ship. They were built and
tested on every CI run throughout, so they could not rot silently while unpublished.

## What did not move

Expand Down
35 changes: 18 additions & 17 deletions docs/release-process.md
Original file line number Diff line number Diff line change
Expand Up @@ -67,32 +67,33 @@ dotnet gitversion

## Which packages the release publishes

Ten projects build; four of them ship. The split is expressed once, in the project files, and
everything else follows from it:
Nine projects build; all nine ship. The split used to hold four of them back is expressed once,
in the project files, so a project that becomes packable is always a one-line change: drop its
`IsPackable` property, and add it to `PublicApiSurfaceTests.Tracked` so its surface is tracked
from its first release.

| Package | Layer | Ships |
| --- | --- | --- |
| `CanKit.Pro.Actor` | L2 — single-threaded protocol actor | yes |
| `CanKit.Pro.Addressing` | L2 — CAN-ID addressing and filters | yes |
| `CanKit.Pro.RawCan` | L2 — raw-CAN demultiplex and TX confirmation | yes |
| `CanKit.Pro.Reliability` | L2 — deadlines, retries, bus-state monitoring | yes |
| `CanKit.Pro.IsoTp` | L3 — ISO 15765-2 | not yet |
| `CanKit.Pro.J1939Tp` | L3 — SAE J1939-21 transport | not yet |
| `CanKit.Pro.CANopen` | L4 — CiA 301 | not yet |
| `CanKit.Pro.J1939` | L4 — J1939 node and address claim | not yet |
| `CanKit.Pro.Uds` | L4 — ISO 14229-1 | not yet |
| `CanKit.Pro.Hawe` | L4 — HAWE private protocol framework | not yet |

The six L3/L4 projects carry `<IsPackable>false</IsPackable>`. `dotnet pack CanKit.Pro.sln`
therefore skips them without needing a list of project names anywhere, which means the CI pack job
and the `@semantic-release/exec` `prepareCmd` cannot drift apart — they run the same command over
the same solution. The CI `pack` job prints `ls -l artifacts/nuget`, so a project that silently
| `CanKit.Pro.IsoTp` | L3 — ISO 15765-2 | yes |
| `CanKit.Pro.J1939Tp` | L3 — SAE J1939-21 transport | yes |
| `CanKit.Pro.CANopen` | L4 — CiA 301 | yes |
| `CanKit.Pro.J1939` | L4 — J1939 node and address claim | yes |
| `CanKit.Pro.Uds` | L4 — ISO 14229-1 | yes |

`dotnet pack CanKit.Pro.sln` packs whichever projects don't set `IsPackable=false`, without
needing a list of project names anywhere, which means the CI pack job and the
`@semantic-release/exec` `prepareCmd` cannot drift apart — they run the same command over the
same solution. The CI `pack` job prints `ls -l artifacts/nuget`, so a project that silently
becomes packable shows up as a new file in that listing on the pull request that did it.

They still build and test on every run, so the unshipped layers cannot rot; they are held back
only until their public API has settled. Publishing one is a one-line change: drop its
`IsPackable` property, and add it to `PublicApiSurfaceTests.Tracked` so its surface is tracked
from the first release like the four L2 packages are.
`CanKit.Pro.Hawe`, the generic extension framework for a customer's confidential private
protocol, used to be the tenth project and stayed unpublished for a different reason: not
API-immaturity but confidentiality. It has since moved out of this public repository entirely
into a separate, internal-only one.

## What a release run does

Expand Down
Loading