Chronos D-Bus API

This documentation covers the Chronos 1.4 Coordinator D-Bus API. The internal camera D-Bus API has two major components: The D-Bus-based Coordinator API (formerly the Control API) and the D-Bus-based Video API.

You can use the internal D-Bus APIs to write your own application on the camera. This application will be able to display a UI on the back of the camera as well as respond to remote HTTP requests over MiniUSB and the network.

If you only need to control the camera remotely, you should consider using the HTTP interface instead. The HTTP interface lets you send commands to the camera over the network, and is used by the (planned) remote-control app. It is easier to develop using the HTTP interface than it is using the D-Bus interfaces.

Note: All examples in this document are given in Python, since the reference client was written in it.

Architecture

The D-Bus Coordinator and Video APIs sit between the hardware and the applications running on the camera.

Chronos 1.4Hardware Coordinator API Video API User Interface(chronos-gui-2) HTTP Interface (planned) Your Client Here

The APIs provide a way to configure the camera hardware. The APIs also emit updates so that clients can keep themselves up-to-date when the camera is reconfigured. For example, if the HTTP interface receives a request to change the exposure time of the camera, then the user interface on the camera will need to update itself to reflect the new exposure time.

Hardware

The APIs primarily drive the FPGA of the Chronos, as well as set up the video pipeline to display and save content. While the FPGA image itself is proprietary, the register definitions are available as part of the implementation of the APIs.

Coordinator API

The Coordinator D-Bus API deals with configuring the camera, as opposed to the video API which is responsible for playing back and saving footage.

Connecting

To connect to the Coordinator API, connect to the D-Bus service/path/interface as in the following example:

from PyQt5.QtDBus import QDBusInterface, QDBusConnection cameraControlAPI = QDBusInterface( "ca.krontech.chronos.control", #Service "/ca/krontech/chronos/control", #Path "", #Interface QDBusConnection.systemBus() )

To use the mock interface, to avoid misconfiguring the camera during development, connect to the ca.krontech.chronos.control.mock service instead of ca.krontech.chronos.control.

Methods

All methods result in a reply containing key/value pairs. The map can contain an optional 'value' entry with the data resulting from the function call, or in the case of an error an 'errorName' and 'message' entry. If there is no errorName, then no error should have occured.

Available methods are:

In addition, when a camera setting is changed, a signal named the key is emitted on the D-Bus interface. It can be intercepted with QDBusConnection.systemBus().connect('ca.krontech.chronos.control.mock', '/', '', NAME_OF_KEY, CALLBACK).

Values

API Values hold and reflect the state of the camera. They are read and written using the get and set method calls listed above. A list of value names can be retrieved by calling the availableKeys method.

Values can have different levels of mutability:

All strings are UTF-8 encoded. All integers are little-endian. All float values are 64-bit IEEE-754 encoded.

Available values are:

Value Name Type Mutability Description
HTTPPort integer variable Specify the port for the web server to run on. This is used for the web app and HTTP API. You can enable the web app and HTTP API by setting localHTTPAccess or remoteHTTPAccess to True.
SSHPort integer variable Set the Secure Shell port. By default, port 22 is used, but it is recommended to use a high random port for day-to-day use. It defaults to port 22 because it's easier to connect to, but it is less secure because this is where everyone looks for SSH.
availableRecording
AnalogGains
list constant Get a list of integer gains the image sensor output can be amplified by. Each element of the list is a map with two keys, multiplier and dB. The multiplier values can be used to set previewAnalogGainMultiplier and recordingAnalogGainMultiplier. The decibel values are purely informational. Higher amplification levels will produce a noisier image. Amplification is an analog operation, versus a digital operation like you might get post-processing a video to be brighter.
batteryCharge float property On a scale of 0.0 to 1.0, how full is the camera battery? 0 is dead, and 1 is fully charged.
batteryVoltage float property A measure of the power the removable battery is putting out, in volts. A happy battery outputs between 12v and 12.5v. This value is graphed on the battery screen on the Chronos.
cameraApiVersion string constant The current iteration of this API. Adheres to SemVer. Example: 1.13.0
cameraDescription string variable Does nothing. Can be used to give an easy-to-identify name to a camera when many cameras are being used. Supports emoji.
cameraFpgaVersion string constant The firmware iteration the field-programmable gate array inside the Chronos is running. (The FPGA is primarily responsible for recording the high-speed video coming off the sensor to a buffer in RAM.) Example: 1.13.0
cameraMemoryGB float constant Amount of RAM installed in the Chronos in GB (vs GiB). This will correspond to the memory amount printed on the bottom of your camera, if you haven't made any modification.
cameraModel string constant The product identifier of the camera hosting the API. This corresponds to the model printed on the bottom of your camera. Example: CR14-1.0
cameraSerial string constant The serial number of the product the API is running on. This corresponds to the SN printed on the bottom of your camera. Example: 00204
colorMatrix list variable A 3x3 matrix controlling colour balance of the recorded video. To disable colour correction, set to the identity matrix: [[1,0,0], [0,1,0], [0,0,1]]
commonlySupported
Resolutions
list constant A list of maps. Each map indicates a preset by specifying hRes (int, px), vRes (int, px), and maximum framerate (float, frames per second). Partial example: [{ 'hRes': 1280, 'vRes': 1024, 'framerate': 1057.362, }, …]
datetime string variable iso 8601-formatted date, YYYY-MM-DDTHH:MM:SS.mmmmmm. Detailed in the Python datetime docs.
currentCameraState enum property Indicates what the camera is doing. One of normal, saving or recording. When saving (to file), parts of the API may be unresponsive. The main difference between normal and recording is whether the red indicator lights on the chronos are red or not. Some actions, like 'stop recording' or 'stop saving', only make sense in certain states.
currentVideoState enum variable Indicates what the video display is showing. One of viewfinder or playback.. In viewfinder mode, the video on the back of the camera is showing what the sensor is seeing. In playback mode, the video is showing footage previously recorded in RAM.
dimScreenWhenNotInUse boolean variable After a period, dim the screen backlight to conserve battery power. This has a fairly small effect overall.
disableOverwriting
RingBuffer
boolean variable In segmented mode, disable overwriting earlier recorded ring buffer segments.
externalStorage list property External storage device partitions.

Returns a list of maps, one map per partition on each external storage device. (Storage devices are things like SD cards, USB thumb sticks, etc.)

Maps contain the following keys:
  • name: The given name of the partition.
  • device: The name of the device the partition is on. If a device has more than one partition, each partition will have the same device name.
  • path: Where on the camera's filesystem the device is mounted to. Unlike name, guaranteed to be unique.
  • size: The amount of space on the partition, in bytes.
  • free: The amount of available space on the partition, in bytes. Note that size and free may not fit in a 32-bit integer.
  • interface: Either a usb drive, an sd card port, or a network mount.
externalStorage example: [{ "name": "Testdisk", "device": "mmcblk0p1", "path": "/dev/sda", "size": 1294839100, #bytes "free": 4591, "interface": "sd", },{ "name": "Toastdesk", "device": "sdc1", "path": "/dev/sdc1", "size": 2930232316000, "free": 1418341032982, "interface": "usb", }]
externallyPowered boolean property Returns True if the camera is running on mains power. In this mode, the battery will recharge until full.
focusPeakingColor integer variable An integer specifying the color of focus peaking, one of the available focus aids. Like HTML/CSS, this value is composed of four packed 8-bit channels, representing Red, Green, Blue, and Alpha (strength). In hexadecimal, this is formatted as 0xRRGGBBAA. For example, 0xAA00AAFF is maximum-strength purple, because red and blue are both set to AA, and alpha is set to FF. 0xC1681988 is half-strength brown.
To turn focus peaking on or off, set focusPeakingIntensity.
focusPeakingIntensity string variable One of 'off', 'low', 'medium', 'high'. Higher intensity means more color on screen.
localHTTPAccess boolean variable Enable web access (HTTP API and web app) over the local network, ie, 192.168.x.x. Note that networkPassword must be set before any network-based control is actually turned on.
localSSHAccess boolean variable Enable command-line access over the local network, ie, 192.168.x.x. Note that networkPassword must be set before any network-based control is actually turned on. It is strongly recommended to set up key-based authentication as soon as possible, and disable ssh password login via the command line.
motionTriggerAdaption string variable Set how quickly the motion triggering algorithm adapts to non-triggering motion sources. Can be set to high, medium, low, or off to disable learning entirely. Even if adaption is disabled, you can call the takeStillReferenceFor
MotionTriggering()
method to retrain the motion trigger.
motionTriggerHOffset integer variable The region within the recorded picture which the motion trigger monitors for activity. HRes is the horizontal size of the box, VRes is vertical size of the box, HOffset is the horizontal offset from the upper-left corner of the recorded image, and VOffset is the vertical offset. (The recorded image can be changed with analogous recordingHRes/VRes/HOffset/VOffset, assuming videoState is 'recording' or 'pre-recording'. Otherwise, no motion triggering occurs.)
See motionTriggerAdaption and takeStillReferenceForMotionTriggering() for configuring motion within the motion trigger region.
motionTriggerHRes integer variable
motionTriggerVOffset integer variable
motionTriggerVRes integer variable
recordingMode string variable Configure how the camera records. 'normal' causes one trigger to record the whole buffer. 'segmented' causes one trigger to record one a segment, the size of which is determined by dividing the total available record length by recordedSegments. gated burst uses the full buffer, but only records when an input signal is high. Signals can be configured by setting triggerConfiguration value.
recordingSegments float variable Set how many individual video clips are produced while in segmented record mode. (See recordingMode for details.) For example, if you wanted to record 4 events, you might call control().set({'recordingSegments': 4, 'recordingMode', 'segmented'})). The minimum is 1, the maximum the of number of frames in the recording buffer. Note that the default on-board UI may not handle viewing extremely large numbers of segments well, since each segment is displayed and saved separately.
recordedSegments list property A list of the recorded segments of video. Will always contain one entry unless recordingMode is 'segmented'. Each entry is a map containing the following keys:
  • int 'start': First frame of the recorded segment, inclusive.
  • int 'end': Final frame of the recorded segment, exclusive.
  • int 'hres': Horizontal resolution of the video, in pixels.
  • int 'vres': Vertical resolution of the video, also in pixels.
  • int 'milliframerate': Framerate the segment was recorded at, in millionths of a frame per second. See sensorMilliframerate for details.
  • string 'id': A unique 8-character identifier for the segment. (Uniqueness is not guranteed long-term. Generate a UUID in that case.)
networkInterfaces list property A list of connections to the outside world through. Add an element to this list by plugging in an Ethernet cable, the On-The-Go Mini USB cable, or a supported Wi-Fi dongle. (No dongles are officially supported yet, however.) Each element contains the following keys:
  • str 'id': The name of the network device, for example, 'enp0s25' or 'wlp4s0'.
  • str 'name': The name of the physical item providing connectivity. Example: 'Ethernet' or 'Mini USB'.
  • str 'localAddress4': The IPv4 address of the camera on the local network. (You can often set up port forwarding to expose this to the internet.) For example, the camera was randomly assigned '192.168.1.14' when I connected it to the office network. Then, using the OTG cable, the camera assigned itself '192.168.12.1' as it always does.
  • str 'localAddress6': The IPv6 address of the camera on the local network. For example, on the office local-area network, I can access the camera at 'fe80::22c3:8fff:fe3b:966a'.
  • str 'remoteAddress4': As with 'localAddress4', but the routable internet address instead of just the local address. You usually have to configure your local network to forward requests to your camera to get this.
  • str 'remoteAddress6': As above, but with IPv6 instead of IPv4.

Note: If no address is available, then the field will be an empty string (''). At least one address will be populated, or the entry will not appear. Remote addresses always have a local version.

For example, using the Python API client, control().get('networkInterfaces') yields [{ 'id': 'enp0s25', 'name': 'Ethernet', 'localAddress4': '192.168.1.135', 'localAddress6': 'fe80::22c3:8fff:fe3b:966a', 'remoteAddress4': '205.250.126.92', 'remoteAddress6': '', },{ 'id': 'wlp4s0', 'name': 'Mini USB', 'localAddress4': '192.168.12.1', 'localAddress6': 'fe80::f81b:26ff:fee7:24dd', 'remoteAddress4': '', 'remoteAddress6': '', }]
networkPassword string variable The password which must be supplied for HTTP or SSH access. If no password is set, network access is disabled. Retrieving this field will yield an arbitrary number of s.
networkStorageAddress string variable Network storage allows the camera to save video to a remote device via a network connection. Address: IP address of the network storage device (ie, a Samba share) to connect to when saving. Password and Username provide authentication. The currently set credentials can be tested by calling testNetworkStorageCredentials({}). If you want to test your credentials before setting them, you can pass them to the function.
networkStoragePassword string variable
networkStorageUsername string variable
playbackFrame int variable The current frame video playback is on. Since this may update very frequently, change events will not fire for this value.
playbackFramerate int variable A delta applied to playbackFrame, once every 16ms at most. Above 60fps, frames will be dropped, and below 60fps, the playbackFrame will be updated less frequently.
powerOnWhen
MainsConnected
boolean variable Set to True to have the camera turn on when it is plugged in. The inverse of this, turning off when the charger is disconnected, is achieved by setting the camera to turn off at any battery percentage. For example, to make the camera turn off when it is unpowered and turn on when it is powered again - effectively only using the battery to finish saving - you could make the following call: api.control('set', { 'powerOnWhenMainsConnected': True, 'saveAndPowerDownWhenLowBattery': True, 'saveAndPowerDownLowBatteryLevel': 100, })
previewAnalog
GainMultiplier
integer variable One of the availableRecordingAnalogGains. Higher values amplify the light level, but as this is an analog operation this also increases image noise. Only used if in preview mode. See also recordingAnalogGainMultiplier.
previewHOffset integer variable Like recordingHOffset/recordingHRes/recordingVOffset/recordingVRes but used for preview mode. If currentCameraState is not set to preview, these properties has no effect.
previewHRes integer variable
previewVOffset integer variable
previewVRes integer variable
recordedSegments list property A list of maps, one for each separate segment of video recorded. Each map having the following keys:
  • str 'id': A short unique random identifier for this segment. Useful for disambiguating segments.
  • int 'start': Start frame (relative to beginning of buffer) of this segment.
  • int 'end': End frame (relative to beginning of buffer) of this segment. Segment length, in frames, may be calculated by subtracting start from end.
  • int 'hres': The horizontal resolution of the recorded video.
  • int 'vres': The vertical resolution of the recorded video.
  • [int 'milliframerate']: The framerate the segment was recorded at. None if recordingMode is 'gated burst', since the camera can't calculate a single framerate from the gating signal in that case.
The maximum number of segments is recordingSegments. There can only be more than one segment if recordingMode was set to 'segmented' while recording.
recordingAnalog
GainMultiplier
integer variable One of the availableRecordingAnalogGains. Higher values amplify the light level, but as this is an analog operation this also increases image noise. Overridden by previewAnalogGainMultiplier when in videoState is 'preview'.
recordingExposureNs integer variable Controls image brightness. Longer exposures lead to a brighter image, but shorter exposures cause less motion blur. The exposure must be 5000ns shorter than the recording period. If set to a value greater than that, it will bump up the recording period appropriately.
recordingPeriod integer variable Value, in nanoseconds, indicating the total amount of time to take to record a frame.
recordingHRes
recordingHoffset
recordingVRes
recordingVoffset
recordingVStep
remoteHTTPAccess boolean variable Enable web access (HTTP API and web app) with no restrictions. The HTTP API and web app will be accessible from any device able to route to it. Note that networkPassword must be set before any network-based control is actually turned on. It is strongly suggested to set networkPassword to a multi-word passphrase in this case, to make it hard to guess.
remoteSSHAccess boolean variable Enable command-line access to the camera with no ip-based restrictions. Note that networkPassword must be set before any network-based control is actually turned on. It is strongly recommended to set up key-based authentication over the local network or the OTG cable (which is always enabled), and disable ssh password login via the command line.
saveAndPowerDown
LowBatteryLevel
saveAndPowerDown
WhenLowBattery
sensorFramerateMax
sensorHIncrement
sensorHMax
sensorHMin
sensorMaxExposureNs
sensorMaxShutterAngle
sensorMilliframerate
sensorMinExposureNs
sensorName
sensorPixelFormat string constant Either BYR2 for color cameras or y12 for monochromatic cameras. This corresponds to the Color or Mono information printed on the bottom of the Chronos.
sensorPixelRate
sensorQuantizeTimingNs
sensorRecordsColor
sensorVIncrement
sensorVMax
sensorVMin
showBlackClipping
ZebraStripes
showWhiteClipping
ZebraStripes
timingExposureDelayNs
timingExposureDelayNs
timingMaxExposureNs
timingMaxPeriod
timingMaxShutterAngle
timingMinExposureNs
timingMinPeriod
timingQuantization
totalAvailableFrames
totalRecordedFrames
triggerCapabilities
triggerConfiguration
triggerDelay in frames
triggerDelayNs in nanoseconds
triggerState
triggers
whiteBalance
videoDisplayDevice
videoDisplayHeight
videoDisplayWidth
videoDisplayX
videoDisplayY
videoState
whiteBalance

Some settings related to the video pipeline take a little while to update, so it's recommended to set them all at once with one call to to set.

Reference Client

A Python reference client for the control API is available. If you're using Python to script, it may be useful as a library. Otherwise, it may serve as a useful example how to connect to and use the D-Bus API.

It is not required to use the reference client. The client simply sands down some of the rough edges of the D-Bus API. For example, when getting or setting a single value, the reference client automatically converts the single value into the list the D-Bus API requires. It also emits an update signal immediately on subscription, which eliminates the need for separate initialiser code in many cases.

The reference API has the following available methods:

Video API

The video interface deals with getting the video data from A to B.

The full documentation for the video API is available in the chronos-cli repository.

User Interface

The user interface, on the screen on the back of the Chronos, uses the D-Bus API to drive the camera and keep itself in sync with the state the camera is in.

HTTP Interface

I have not written this program yet, but what is documented as follows will follow.

The HTTP interface exposes a web API. It also provides web app which uses the web API. The web app can be used from any phone, tablet, or laptop running a modern web browser.

The HTTP interface is very similar to the D-Bus interface. It mostly exposes the same method calls, and provides the same events. However, it also contains an authentication mechanism so other people can't control your camera without your permission. The D-Bus API does not need an authentication mechanism, since anything capable of talking to it is already running on the camera and can do anything the API can do.

Your Client Here

So, you have a specialized application you want the camera to perform? Perhaps you just want to lock down the back-of-camera UI? Luckily for you, it is easy to develop your own application to run on the Chronos.

There are two approaches to developing an app. You can write the code on the camera, or you can write the code on a virtual machine and copy it to the camera later. If you want to set up a VM, refer to ~util/chronos debian setup instructions.txt. The following instructions assume you have a working development environment, either on the camera or in a virtual machine.

Connecting to the Camera

Developing directly on your Chronos, via SSH or file upload, is simpler than developing on a virtual machine. If you develop via SSH, you'll usually run commands and edit files in-place on the camera with Vim or Emacs. If you prefer file upload, you'll set up a little watcher-script that will restart your application when you change a file. The advantage of uploading the files is being able to edit them locally, with your preferred text editor, although this method is a little more complex. Either way the files on the camera are changed, the result is the same.

Before making any changes to your camera, it is strongly recommended to make a backup of your system SD card. Pop the SD card out of the bottom of the camera, insert it into your computer, and then make a backup of the card filesystems. (Not the files themselves.) On Linux, this can be done with gzip /dev/sdb --to-stdout --verbose > chronos-fs-$(date +%F).gz, where /dev/sdb is the device you just plugged in. You can list plugged-in devices with lsblk. (You should see BOOT and ROOTFS on your microSD card.) After you've taken your backup, which will take a while to complete, test it by restoring it to a different microSD card. If you don't have a spare card to test with, it is advised to say a brief prayer instead.

You can connect via the local network by plugging an Ethernet cable into your camera, or connect directly to your computer with a MicroUSB cable. Either way, the camera will get an IP address which you can SSH to. For example, I have my camera connected to my PC via USB, so I run ssh root@192.168.12.1 to connect to my camera. I can also visit fish://root@192.168.12.1/root/ in Dolphin to browse the files on my camera graphically. When prompted, the password is "chronos", or whatever you set it to.

The camera runs Debian 7 (Wheezy). As such, most common linuxisims will still work, but modern programs must be compiled from scratch. The back-of-camera UI, chronos-gui-2, lives in ~/gui. For your own app, you may wish to build new screens for chronos-gui-2, or use it as a reference for developing your own Qt app. The D-Bus API resides in ~/chronos-cli. All software running on the CPU is open source, and can be freely downloaded from GitHub. If you'd like to contribute a bug fix or a new feature to the existing app, please drop us a line on the forum so we can coordinate!

So, basically, make a new my_client_app.py file on the camera and run it with python3 my_client_app.py. Refer to above for how to make it do stuff.