Skip to content

Streetblock/remote-camera-control-rs

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

67 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

remote-camera-control-rs

remote-camera-control-rs is a Rust-first port of the portable Sony camera control core from the original Swift-based rocc project.

The long-term goal is a reusable library for Android, Windows, and Linux frontends, with a small CLI kept as a debug and integration tool rather than the main product surface.

This is currently a Sony-first project. The public library direction is broader, but the real-world validation and protocol coverage today are focused on Sony Alpha cameras.

This is an unofficial community project and is not affiliated with or endorsed by Sony.

Build

cargo fmt --check
cargo test

Quick Start

cargo run -p rocc-cli -- discover
cargo run -p rocc-cli -- ptp-status 5

What It Supports Today

  • Sony camera discovery over SSDP, dd.xml, and DigitalImagingDesc.xml
  • backend routing between:
    • ScalarWebAPI for older Sony bodies
    • DigitalImaging as metadata/capability discovery
    • PTP/IP for newer Sony bodies
  • generic library reads for Sony parameters:
    • discover()
    • connect()
    • get_parameter()
    • set_parameter()
    • get_parameter_options()
  • high-level live view entrypoint for ScalarWebAPI cameras:
    • SonyCameraConnection::start_live_view()
  • Sony PTP/IP session setup:
    • command channel
    • event channel
    • OpenSession
    • GetDeviceInfo
    • Sony SDIO extension handshake
    • getAllDevicePropData (0x9209)
  • decoded Sony parameter values such as:
    • aperture
    • ISO
    • shutter speed
    • white balance
    • exposure mode
    • exposure compensation
    • focus mode
    • focus status

Real Camera Validation

The following cameras have been exercised against the current Rust port:

  • Sony ILCE-7M3 (a7 III)
    • discovered through the classic ScalarWebAPI path
  • Sony ILCE-6700 (a6700)
    • discovered through DigitalImaging
    • controlled through PTP/IP
    • confirmed parameter reads
    • confirmed parameter writes for:
      • ISO
      • aperture
      • shutter speed
      • exposure compensation
      • white balance

Backend Model

remote-camera-control-rs treats Sony support as one library with multiple transport/control backends:

  • ScalarWebAPI
    • legacy Sony HTTP/JSON-RPC path
    • still important for older bodies like the a7 III
  • DigitalImaging
    • not treated as the primary control API
    • used as a capability and routing layer for modern cameras
    • especially useful for discovering PTP support
  • PTP/IP
    • primary control path for newer cameras like the a6700
    • the main focus for modern Sony support

Parameter Option Semantics

When you query parameter options, remote-camera-control-rs keeps two Sony-specific concepts separate:

  • available
    • values the camera reports as currently selectable in the present mode/state
  • supported
    • values the camera reports as part of the wider capability set

Some Sony bodies do not report a useful available list for every parameter even when they do report supported. In those cases the CLI shows available: none reported by the camera and the library still returns the supported set.

Status By Backend

Backend Discovery Read Write Notes
ScalarWebAPI Good Good for mapped getters Initial generic setter path Best for older cameras
DigitalImaging Good Metadata/capabilities Not a primary write path Used for routing and PTP capability detection
PTP/IP Good Good for mapped parameters Good for validated parameters Main modern Sony path

Stable PTP Parameter Writes

The following parameters are currently marked as Stable for the PTP write path:

  • ISO
  • aperture
  • shutter speed
  • exposure compensation
  • white balance

Known Limits

  • the public API is intentionally still small
  • event-driven live synchronization is not complete yet
  • live view is still more diagnostic than productized
  • not every Sony-specific property has a friendly name or value mapping yet
  • ScalarWebAPI coverage is solid for the basics but still narrower than the modern PTP path

First Release Notes

  • current scope is intentionally Sony-first
  • a7 III and a6700 are the primary real hardware validation targets so far
  • older Sony bodies are expected to favor ScalarWebAPI
  • newer Sony bodies are expected to favor PTP/IP
  • multi-vendor support is a future direction, not part of the current release target

Workspace Layout

  • crates/rocc-cli
    • debug/example frontend for discovery, probing, and end-to-end camera testing
  • crates/rocc-core
    • shared camera models, values, descriptors, and error types
  • crates/rocc-discovery
    • SSDP/UPnP discovery and Sony device-description parsing
  • crates/rocc-net
    • small networking primitives used by the higher layers
  • crates/rocc-ptp
    • PTP/IP transport, Sony SDIO handshake, property parsing, and status decoding
  • crates/rocc-sony
    • Sony-specific routing plus the high-level library API

Library Example

use std::time::Duration;

use rocc_core::SonyParameterId;
use rocc_sony::{connect, discover};

fn main() -> Result<(), Box<dyn std::error::Error>> {
    let timeout = Duration::from_secs(5);
    let devices = discover(timeout)?;
    let device = devices
        .into_iter()
        .find(|device| device.connection_mode().is_some())
        .expect("no Sony camera found");

    let mut camera = connect(&device, timeout)?;
    let iso = camera.get_parameter(SonyParameterId::Iso)?;
    let options = camera.get_parameter_options(SonyParameterId::Iso)?;

    println!("ISO: {:?}", iso);
    println!("ISO options: {}", options.supported.len());
    Ok(())
}

Scalar Live View Example

The library exposes a high-level live view entrypoint on the connection itself. It chooses the backend-specific setup path internally:

  • older bodies such as the a7 III use the classic ScalarWebAPI start/stop flow
  • newer bodies such as the a6700 can resolve the stream URL through PTP/IP and then reuse the same HTTP live view reader
use std::time::Duration;

use rocc_sony::{connect, discover};

fn main() -> Result<(), Box<dyn std::error::Error>> {
    let timeout = Duration::from_secs(5);
    let devices = discover(timeout)?;
    let device = devices
        .into_iter()
        .find(|device| device.connection_mode().is_some())
        .expect("no Sony camera found");

    let connection = connect(&device, timeout)?;
    let mut live_view = connection.start_live_view(Some("L"), true)?;
    let report = live_view.read_payloads(262_144)?;

    println!("stream bytes: {}", report.bytes.len());
    println!("payloads: {}", report.payloads.len());

    live_view.stop()?;
    Ok(())
}

For the current modern Sony path, stop() is intentionally treated as a successful no-op on PTP/IP until a camera-specific teardown step proves necessary.

If you do not need manual session handling, there is also a top-level helper on the connection:

use std::time::Duration;

use rocc_sony::{connect, discover};

fn main() -> Result<(), Box<dyn std::error::Error>> {
    let timeout = Duration::from_secs(5);
    let device = discover(timeout)?
        .into_iter()
        .find(|device| device.connection_mode().is_some())
        .expect("no Sony camera found");

    let mut connection = connect(&device, timeout)?;
    let report = connection.capture_live_view_frames(Some("L"), false, 262_144)?;

    println!("payloads: {}", report.payloads.len());
    println!("images: {}", report.image_count());
    println!("jpeg bytes: {}", report.total_jpeg_bytes());
    println!("jpeg frames: {}", report.jpeg_frames().len());
    Ok(())
}

For longer reads there are now two ergonomic layers:

  • library:
    • connection.start_live_view(...) for manual session control
    • connection.capture_live_view_frames(...) for one bounded read window
    • connection.capture_live_view_jpeg_frames(...) when only JPEG payloads matter
    • connection.capture_live_view_chunks(...) for repeated chunk reads
    • connection.for_each_live_view_chunk(...) for callback-style chunk handling
    • connection.for_each_live_view_jpeg_frame(...) for callback-style JPEG frame handling
  • CLI:
    • liveview-rocc for one bounded window
    • liveview-stream for repeated chunk reads over one open session

Here is the intended callback-style library path for continuous JPEG frame handling:

use std::time::Duration;

use rocc_sony::{connect, discover};

fn main() -> Result<(), Box<dyn std::error::Error>> {
    let timeout = Duration::from_secs(5);
    let device = discover(timeout)?
        .into_iter()
        .find(|device| device.connection_mode().is_some())
        .expect("no Sony camera found");

    let mut connection = connect(&device, timeout)?;
    let processed = connection.for_each_live_view_jpeg_frame(
        Some("L"),
        false,
        5,
        131_072,
        Some(8),
        |jpeg| {
            println!("frame: {} bytes", jpeg.len());
            Ok(())
        },
    )?;

    println!("processed {processed} jpeg frame(s)");
    Ok(())
}

The same example also lives in:

  • cargo run -p rocc-sony --example liveview_callback

CLI Positioning

The CLI is intentionally kept in the repo because it is extremely useful for:

  • validating new cameras
  • comparing ScalarWebAPI and PTP/IP behavior
  • investigating Sony-specific properties
  • reproducing real hardware issues quickly

It should be thought of as a companion debug tool and example consumer of the library, not the final public surface.

About

Rust library and CLI for Sony camera discovery, control, and live view across ScalarWebAPI and PTP/IP

Topics

Resources

License

Apache-2.0, MIT licenses found

Licenses found

Apache-2.0
LICENSE-APACHE
MIT
LICENSE-MIT

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors