Blazor app with can interface
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

86 lines
3.4 KiB

1 week ago
# CLAUDE.md — IO Module Blazor Dashboard
## Project Overview
Blazor Server app (.NET 10) for monitoring and controlling the STM32H723ZG Nucleo IO module. Communicates over CAN (via PCAN-USB adapter) and serial (via ST-Link VCP).
## Architecture
```
PCAN Hardware ──► CanWorker (IHostedService) ──► CanService (singleton) ──► Razor pages
ST-Link VCP ──► SerialPortService (singleton, event-driven) ──► SerialTerminal.razor
```
- **Blazor Server** — all C# runs server-side; browser connects via WebSocket/SignalR
- **No background worker for serial** — `System.IO.Ports.SerialPort` fires `DataReceived` events internally; `SerialPortService` handles buffering directly
## Key Files
| File | Purpose |
|------|---------|
| `Services/ICanService.cs` / `CanService.cs` | PCAN adapter: send, receive, filter, signal extraction |
| `Services/ISerialPortService.cs` / `SerialPortService.cs` | Serial port: open/close, send lines, receive buffer |
| `CanWorker.cs` | `IHostedService` — continuous CAN RX loop, loads config from `appsettings.json` |
| `Models/CanModels.cs` | `CanMessageDto`, `CanFilter`, `CanBitmask` |
| `Components/Pages/Home.razor` | Button status + termination toggles + CAN message list |
| `Components/Pages/CanMonitor.razor` | Full CAN UI: connect, stream, filters, bitmasks, send |
| `Components/Pages/SerialTerminal.razor` | Serial terminal for NVMEM commands |
## CAN Sending Pattern
```csharp
// PcanMessage.Data is read-only — pass data via the constructor, NOT object initializer + CopyTo
var data = new byte[8];
data[0] = payload;
var msg = new PcanMessage(0x240, MessageType.Standard, 8, data, false);
var result = CanService.Write(msg); // returns PcanStatus.OK on success
```
## UI State Update Pattern
Pages poll `CanService.GetLatestMessages()` via a `Timer` (50ms on Home, 100ms on CanMonitor):
```csharp
_updateTimer = new Timer(_ => InvokeAsync(() => { /* update state */ StateHasChanged(); }), null, 0, 50);
```
Serial terminal subscribes to `ISerialPortService.DataReceived` event instead of polling.
## CAN Message Map
| ID | Direction | Handler |
|----|-----------|---------|
| 0x210 | RX | User button → `button1Active` in Home.razor |
| 0x220 | RX | CN9-29 button → `button2Active` |
| 0x230 | RX | CN9-30 button → `button3Active` |
| 0x240 | TX | Termination control — sent from `Home.razor:SendTermination()` |
| 0x250 | RX | Termination pin status — bit0=TERM_ON, bit1=TERM_OFF; syncs `_termOn`/`_termOff` in Home.razor |
| 0x241 | TX | NVMEM write — sent from SerialTerminal via CAN (if needed) |
| 0x242 | TX | NVMEM read request |
| 0x243 | RX | NVMEM read response |
## CAN Config (`appsettings.json`)
```json
"CanOptions": {
"Channel": "", // empty = auto-scan PCAN USB
"Bitrate": "Pcan500",
"Filters": [], // CanFilter objects
"Bitmasks": [] // CanBitmask objects for signal extraction
}
```
## Serial Port Notes
- `SerialPortService` is a singleton — only one port open at a time
- Buffers last 200 lines; sent lines prefixed `> `, received prefixed `< `
- NVMEM commands: `r <addr_hex> <len>` and `w <addr_hex> <bytes...>` at 115200 baud
- Full command reference: `../STM32Nucleo/docs/NVMEMCommands.md`
## Build / Run
```
dotnet run --project IOModuleTestBlazor
```
Requires PCAN-Basic drivers installed. Serial port access requires the app to run with permission to open COM ports (no special config needed on Windows).