Architecture and development
.NET 8, solution SigmaFpAlpaca.sln.
| Project | Role |
|---|---|
src/SigmaFp.Camera |
USB (libusb-win32), PTP framing, Sigma vendor messages, camera worker thread, state machine, reconnect, simulator, bulb relay (simulator only: the cameras ignore the remote jack under USB control) |
src/SigmaFp.Imaging |
managed DNG reader and lossless-JPEG (ITU T.81 process 14) decoder |
src/SigmaFp.Alpaca |
ASP.NET Core Alpaca server (ICameraV4), discovery, setup page, settings, Windows service |
tools/CameraCli |
hardware test host (timed frames, fault tests) |
tools/DngToTiff |
interpolation-free DNG to TIFF converter with flat-field correction |
tools/install |
release build and install/uninstall scripts |
tests/* |
xUnit tests (camera layer against a simulator; protocol bytes; PTP framing; DNG decoding; HTTP API) |
Design rules
- One camera worker thread does all USB and serial I/O. Everything else posts work to it.
- Timeouts everywhere: every USB transfer has one, and a watchdog abandons a work item (and its thread) that exceeds its limit, then reconnects. A stuck native call never hangs a client.
- Explicit state machine: Disconnected > Idle > Exposing > Downloading > Idle, plus Error.
- USB loss is reported as Error, then reconnected with backoff (1, 2, 5, 10 s); no client restart.
- Never close the camera session during a capture. A camera abandoned mid-bulb refuses all captures until power-cycled; a disconnect during a capture is deferred.
- Never issue a USB port reset; recover by closing and reopening.
- Raw data untouched: only DNG decoding; no black subtraction, scaling or debayering.
ImageReadybecomes true only after the full image is decoded in memory.- Per-client connections (Alpaca ClientID): the camera is released when the last client disconnects.
Exposure handling
| Request | Method |
|—|—|
| <= 30 s | camera-timed shutter (nearest APEX step), Snap non-AF |
| = 300 s | Bulb + Snap non-AF; the camera ends it at its own limit (cannot be aborted) |
| 60-180 s (any 1-300 s) | Mass Storage mode: MassStorageSession (USB port off via YKUSH XS, relay bulb via MassStorageTrigger, port on, newest DNG from the card via WindowsCardLocator); under USB control not possible (the camera ignores the remote jack) |
A lost frame keeps CameraState = Error until the next StartExposure, so clients do not wait for their timeout. StartExposure while an un-abortable capture is still finishing is queued.
Building and testing
dotnet test # ~100 tests, ~15 s
powershell -File tools\install\Build-Release.ps1 # tests + self-contained publish\
src\SigmaFp.Alpaca\bin\...\SigmaFp.Alpaca.exe --simulate # driver with a simulated camera
Environment overrides (tests): SIGMAFP_SETTINGS=<path>, SIGMAFP_SIMULATE=1, SIGMAFP_NODISCOVERY=1.
Conformance: conformu conformance http://127.0.0.1:11111/api/v1/camera/0 and
conformu alpacaprotocol ... (ASCOM ConformU 4.5).
Camera facts (measured)
| | fp L | fp | |—|—|—| | USB ID | 1003:C442 | 1003:C432 | | Raw (DNG) size | 9536 x 6344 | 6064 x 4042 | | DefaultCrop | 9520 x 6328 | 6000 x 4000 | | Pixel | 3.76 um | 5.98 um | | Raw data | 14-bit, black 1024, white 16383, RGGB | same | | DNG encoding | 256 x 256 tiles, lossless JPEG | lossless JPEG | | BaselineExposure | +0.94 EV | +1.0 EV | | Camera bulb limit | 300 s | 300 s (assumed same) |
See Protocol notes for the wire format.