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
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).
|