Documentation Index
Fetch the complete documentation index at: https://crsdk.app/llms.txt
Use this file to discover all available pages before exploring further.
AlphaSDK is the official Swift client for the Alpha Camera REST API. It uses URLSession only (zero third-party dependencies) and exposes Swift concurrency throughout.
Install
Add to your Package.swift dependencies:
.package(url: "https://github.com/jordlee/alpha-sdk-swift.git", from: "0.3.1"),
Then add AlphaSDK to your target’s dependencies:
.target(
name: "MyApp",
dependencies: [
.product(name: "AlphaSDK", package: "alpha-sdk-swift"),
]
)
In Xcode: File → Add Package Dependencies…, paste the URL, choose from 0.3.1.
You also need a server reachable from the device. The Swift client does not ship a ServerManager class — start the server using the Node-based CLI from the server package, or, on macOS, spawn the bundled binary from your application using Process (recipe). iOS applications typically connect over the local network to a server running on a Mac, Raspberry Pi, or similar host.
Initialize
import AlphaSDK
let client = AlphaSDKClient(baseURL: "http://localhost:8080")
Constructor options
let client = AlphaSDKClient(
baseURL: "http://192.168.1.50:8080", // base URL — defaults to localhost:8080
headers: ["X-Trace-Id": "abc123"], // applied to every request
timeout: 30, // seconds
maxRetries: 3,
urlSession: .shared // bring your own URLSession
)
AlphaSDKClient is Sendable and safe to share across actors.
Common operations
List + connect a camera
let cameras = try await client.cameras.list()
guard let cameraId = cameras.cameras.first?.id else { return }
try await client.cameras.connect(
cameraId: cameraId,
request: .init(mode: .remoteTransfer, reconnecting: .on)
)
// Required for the host PC to drive most settings:
try await client.properties.setPriorityKey(
cameraId: cameraId,
request: .init(setting: .pcRemote)
)
Read a single property
let aperture = try await client.properties.get(
cameraId: cameraId,
propertyName: "aperture"
)
print(aperture.data.value, aperture.data.formatted)
Read every property at once
let res = try await client.properties.getAll(cameraId: cameraId)
for (name, entry) in res.data.properties {
print(name, entry.currentFormatted, "writable=\(entry.writable)")
}
// `properties` is a [String: BulkPropertyEntry]; entries use the
// `current_*` field shape (NOT the same as single-property GET).
Set a property
try await client.properties.set(
cameraId: cameraId,
propertyName: "shutter-speed",
request: .init(value: "1/250")
)
Trigger the shutter
// Single shot — pass an empty request body.
try await client.actions.shutter(cameraId: cameraId, request: .init())
// Continuous shooting (set drive mode to a continuous mode first):
try await client.actions.shutter(cameraId: cameraId, request: .init(action: .down))
// ... hold ...
try await client.actions.shutter(cameraId: cameraId, request: .init(action: .up))
Pull a single live-view JPEG
let data: Data = try await client.liveView.getFrame(cameraId: cameraId)
#if canImport(UIKit)
let image = UIImage(data: data)
#elseif canImport(AppKit)
let image = NSImage(data: data)
#endif
For OSD-overlaid frames after try await client.liveView.enableOsd(cameraId: cameraId):
let data = try await client.liveView.getOsdFrame(cameraId: cameraId)
See the live-view polling recipe for a render loop.
Disconnect
try await client.cameras.disconnect(cameraId: cameraId)
Error handling
Every method throws AlphaSDKError, an enum with cases for transport
failures and HTTP responses. Pattern-match the case (or, for HTTP responses,
classify with HTTPError.kind):
import AlphaSDK
do {
try await client.properties.set(
cameraId: cameraId,
propertyName: "aperture",
request: .init(value: "F1.0") // not a valid value on this lens
)
} catch let AlphaSDKError.httpError(http) {
switch http.kind {
case .validation, .client:
print("server rejected the value (\(http.statusCode)):", http.body?.message ?? "")
case .notFound:
print("camera no longer connected")
default:
print("server error \(http.statusCode):", http.body?.message ?? "")
}
} catch AlphaSDKError.timeout {
print("request timed out")
} catch let AlphaSDKError.networkError(underlying) {
print("network error:", underlying)
} catch {
print("unexpected error:", error)
}
HTTPError exposes statusCode, parsed body (with message / code / type),
and kind (.notFound, .validation, .client, .server, …). All other
failure modes are dedicated cases on AlphaSDKError itself
(.timeout, .networkError, .decodingError, …).
Advanced
try await client.cameras.list(
requestOptions: .init(additionalHeaders: ["X-Trace-Id": "request-42"])
)
Cancellation
Swift’s structured concurrency does the right thing — wrap the call in a Task and cancel:
let task = Task {
try await client.properties.getAll(cameraId: cameraId)
}
// elsewhere:
task.cancel()
Bring your own URLSession
Useful for proxying, intercepting, or testing:
let config = URLSessionConfiguration.default
config.protocolClasses = [MyMockURLProtocol.self]
let urlSession = URLSession(configuration: config)
let client = AlphaSDKClient(
baseURL: "http://localhost:8080",
urlSession: urlSession
)
What’s NOT in the client
By design, the following live in recipes rather than the generated SDK:
Versioning
AlphaSDK follows SemVer. Every release is git-tagged on the SwiftPM repository — see the CHANGELOG there for release notes.