69 lines
3.1 KiB
Markdown
69 lines
3.1 KiB
Markdown
# ExperionCrawler — Agent Instructions
|
|
|
|
## Build / Run / Test
|
|
|
|
| Action | Command | Working Dir |
|
|
|--------|---------|-------------|
|
|
| Build | `dotnet build src/Web/ExperionCrawler.csproj` | repo root |
|
|
| Run (dev) | `dotnet run` | `src/Web/` |
|
|
| Publish | `dotnet publish -c Release -o /opt/ExperionCrawler` | `src/Web/` |
|
|
| Tests | `dotnet test` | repo root |
|
|
|
|
Single project: `src/Web/ExperionCrawler.csproj`. Core and Infrastructure are included via `<Compile Include>` globs — there are no separate projects to build. Runtime target is `linux-arm64`.
|
|
|
|
## Architecture
|
|
|
|
```
|
|
src/
|
|
├── Core/ — Interfaces (IExperionServices.cs), Domain entities, DTOs, Application Services
|
|
├── Infrastructure/ — OpcUa/, Database/, Certificates/, Csv/, Mcp/
|
|
└── Web/ — Program.cs, Controllers/, wwwroot/ (SPA)
|
|
```
|
|
|
|
All controllers are in `src/Web/Controllers/ExperionControllers.cs` (single file). All interfaces are in `src/Core/Application/Interfaces/IExperionServices.cs` (single file).
|
|
|
|
## Database
|
|
|
|
**PostgreSQL** (NOT SQLite — README is stale). Connection strings in `src/Web/appsettings.json`. TimescaleDB extension may be enabled on `history_table` via DDL only; no app code changes needed.
|
|
|
|
## Critical Convention — JSON camelCase
|
|
|
|
`PropertyNamingPolicy = null` in Program.cs means C# PascalCase becomes JSON keys. **Frontend expects camelCase**. Every controller `Ok(...)` response MUST use explicit anonymous objects with camelCase keys:
|
|
|
|
```csharp
|
|
// ✅ Correct
|
|
return Ok(new { id = x.Id, tagName = x.TagName });
|
|
|
|
// ❌ Broken — JS gets undefined
|
|
return Ok(new { x.Id, x.TagName });
|
|
return Ok(myDto); // typed object
|
|
```
|
|
|
|
See `CODING_CONVENTIONS.md` for full details and checklist.
|
|
|
|
## Background Services (HostedServices in Program.cs)
|
|
|
|
- `ExperionRealtimeService` — OPC UA subscription, 500ms batch flush to DB
|
|
- `ExperionHistoryService` — periodic snapshot (60s) from realtime_table → history_table
|
|
- `ExperionOpcServerService` — exposes realtime data as OPC UA server (port 4841)
|
|
- `McpServerHostedService` — Python MCP server bridge
|
|
- `ExperionFastService` — high-frequency data capture sessions
|
|
- `ExperionFastCleanupService` — expired session cleanup
|
|
|
|
All registered as Singleton + HostedService. RealtimeService and OpcServerService share autostart flag files (`realtime_autostart.json`, `opcserver_autostart.json`) in the working directory.
|
|
|
|
## Frontend
|
|
|
|
Vanilla JS SPA. `wwwroot/index.html` + `js/app.js` + `css/style.css`. No build step. Tab-based navigation; tabs do NOT auto-fire API calls on entry (performance fix).
|
|
|
|
## OPC UA SDK Gotchas
|
|
|
|
- SDK v1.5.378.134 — `Session.Create()` is `[Obsolete]`; use `DefaultSessionFactory.CreateAsync()`
|
|
- `Subscription.Create()` / `Delete()` / `ApplyChanges()` also deprecated → async variants preferred
|
|
- Certificate validation must be attached AFTER `OpcUaConfigProvider.GetConfigAsync()` returns the config
|
|
- TCP connect timeout: wrap `SelectEndpointAsync` with a 10s `CancellationTokenSource` (OS default is 127s)
|
|
|
|
## Deploy
|
|
|
|
`sudo bash deploy.sh` — publishes to `/opt/ExperionCrawler`, creates systemd service `experioncrawler`, sets up PKI dirs. Service runs as `www-data`.
|