- STACK.md - Technologies and dependencies (.NET 4.7.2, NuGet, Costura.Fody) - ARCHITECTURE.md - Layered CLI with ICncMachine factory pattern - STRUCTURE.md - Directory layout and where to add new code - CONVENTIONS.md - C# style, naming, result wrapper pattern - TESTING.md - NUnit 3 + Moq, stubs, ignored FOCAS tests - INTEGRATIONS.md - FOCAS, LSV2, FTP, RSA licensing - CONCERNS.md - Blocking async, silent catch, no logging, Windows-only Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
5.9 KiB
5.9 KiB
Architecture
Analysis Date: 2026-05-18
Pattern Overview
Overall: Layered CLI console application with abstract machine interface, factory dispatch, and offline license gate.
Key Characteristics:
- Single Windows EXE (all dependencies embedded via Costura.Fody)
- Polymorphic multi-vendor CNC support via
ICncMachineinterface - Factory pattern for manufacturer selection at runtime
- Async/await throughout (Task-based), but blocked at CLI boundary via
.GetAwaiter().GetResult() - Result-wrapper pattern (
CncResult<T>) instead of exceptions for CNC operations - RSA license validation gate on every startup
Layers
CLI Entry Layer:
- Purpose: Parse args, validate license, dispatch to action (Scarica/Invia)
- Contains:
Program.cs(main orchestration),ArgParser.cs(regex arg parsing),InputArgs.cs(config object) - Depends on: Licensing layer, CNC abstraction layer
- Error output: Negative exit codes (-100 to -208) mapped to Italian user messages
Licensing Layer:
- Purpose: Prevent execution on unlicensed machines
- Contains:
Licensing/LicenseValidator.cs,Licensing/MachineFingerprint.cs,Licensing/LicenseFile.cs - Depends on: WMI (System.Management), RSA crypto
- Used by: CLI entry layer (startup check only)
CNC Abstraction Layer:
- Purpose: Uniform interface over 4 different CNC protocols
- Contains:
Cnc/ICncMachine.cs,Cnc/IFanucMachine.cs,Cnc/CncMachineFactory.cs,Cnc/Models/ - Key types:
CncResult<T>,CncError,CncManufacturer,ConnectionState,CncProgram - Used by: CLI entry layer
Manufacturer Implementations:
- Purpose: Protocol-specific CNC communication
- Contains:
Cnc/Fanuc/,Cnc/Heidenhain/,Cnc/Siemens/,Cnc/Mitsubishi/ - Each implements
ICncMachine(Fanuc also implementsIFanucMachine) - Depends on: Protocol libraries (FOCAS DLL, TCP socket, FtpWebRequest)
Validation Layer:
- Purpose: Pre-upload NC program syntax checking
- Contains:
Cnc/INcProgramValidator.cs,Cnc/NcProgramValidator.cs - Injected into machine implementations; upload blocked on Error severity
- Depends on: Nothing external
NC Program Parsing:
- Purpose: Parse/format Fanuc composite NC file format
- Contains:
FanucProgram.cs(program + tooloffset + workzero sections) - Used by: CLI entry layer post-download
Data Flow
Scarica (Download from CNC):
CLI args
→ ArgParser.Parse() → InputArgs
→ LicenseValidator.Validate() [exit -1xx on failure]
→ CncMachineFactory.Create(InputArgs) → ICncMachine
→ machine.ConnectAsync() → CncResult<bool>
→ machine.ReadProgramAsync(path) → CncResult<string>
→ [IFanucMachine cast] ReadToolDataAsync / ReadWorkZeroDataAsync
→ FanucProgram.Format() → composite file string
→ File.WriteAllText(localPath)
Invia (Upload to CNC):
CLI args
→ ArgParser.Parse() → InputArgs
→ LicenseValidator.Validate() [exit -1xx on failure]
→ CncMachineFactory.Create(InputArgs) → ICncMachine
→ File.ReadAllText(localPath)
→ NcProgramValidator.Validate() [exit on Error severity]
→ machine.ConnectAsync()
→ machine.WriteProgramAsync(path, content) → CncResult<bool>
State Management:
- No persistent in-memory state between invocations (each run is independent)
- Machine state tracked per-instance:
ConnectionStateenum +StateChangedevent - Thread safety:
SemaphoreSlimgate per machine instance
Key Abstractions
ICncMachine:
- Purpose: Uniform contract for all CNC machines
- Location:
Cnc/ICncMachine.cs - Methods:
ConnectAsync,DisconnectAsync,ReadProgramAsync,WriteProgramAsync,ReadAsync,DeleteProgramAsync,ReadActiveProgramAsync,SelectMainProgramAsync - Pattern: Interface + factory dispatch
IFanucMachine:
- Purpose: Fanuc-specific extensions (tool offsets, work zero)
- Location:
Cnc/IFanucMachine.cs - Extends:
ICncMachine - Pattern: Interface specialization
CncResult:
- Purpose: Typed result wrapper replaces exception-based control flow
- Location:
Cnc/Models/CncResult.cs - Factories:
Ok(),Fail(),Cancelled(),OkWithWarnings() - Properties:
Success,Errors,WasCancelled,Value
IFocasDialect:
- Purpose: Abstract FOCAS version differences (Legacy vs Modern API)
- Location:
Cnc/Fanuc/IFocasDialect.cs - Implementations:
LegacyFocasDialect.cs,ModernFocasDialect.cs - Detection:
FanucDialectDetector.csat connect time
CncMachineFactory:
- Purpose: Create correct ICncMachine from InputArgs
- Location:
Cnc/CncMachineFactory.cs - Dispatches on:
CncManufacturerenum (Fanuc, Heidenhain, Siemens, Mitsubishi)
Entry Points
CLI Entry:
- Location:
Program.cs(Main method) - Triggers: Process execution from command line or calling application
- Responsibilities: Arg parsing → license check → machine factory → action dispatch → exit code
Argument Parser:
- Location:
ArgParser.cs(staticParse(string[])) - Returns:
InputArgswith all 16 CLI parameters normalized
Error Handling
Strategy: Result wrapper at CNC layer, exit codes at CLI boundary, ArgumentNullException for null guards
Patterns:
CncResult<T>.Fail(errors)for CNC operation failuresArgumentNullExceptionfor constructor null guards (Cnc/Fanuc/FanucMachine.cs)- Exit codes -100 to -208 in
Program.csfor user-facing errors try/finallywithconnectedflag for connection leak prevention (Program.cs)catch { }(silent) on disconnect cleanup paths — known weakness (see CONCERNS.md)
Cross-Cutting Concerns
Logging:
Console.WriteLineonly — no structured logging framework- Debug mode (
-debug=arg): keeps terminal open after operation
Validation:
NcProgramValidatorinjected into machine constructors- Runs before upload; blocked on
ValidationSeverity.Error
Cancellation:
CancellationTokenpassed through all async methods- CLI does not currently expose cancellation to user
Architecture analysis: 2026-05-18 Update when major patterns change