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.
85 lines
3.4 KiB
85 lines
3.4 KiB
# 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).
|
|
|