This is a description of the Cambrionix Hub API that can be used to control Cambrionix PD-Sync and Universal charging units that use the Cambrionix Very Intelligent Charging Protocol.
The Cambrionix Hub API resides in a locally installed daemon called
CambrionixApiService
. This provides a programming language
independent JSON-RPC
interface to control Cambrionix units connected to the local machine.
The Cambrionix Hub API can also connect with Cambrionix units that are
connected to the network e.g. EtherSync.
A simple Python wrapper is provided with a public domain JSON-RPC library that will allow scripts to be written without needing to be overly familiar with JSON. Alternatively you may use the programming language of your choice to connect directly to the daemon over a standard TCP/IP socket and send and receive JSON formatted data.
When the Hub API is used to communicate with a remote network attached Cambrionix unit this is done over an SSH tunnel.
The Cambrionix Hub API supports multiple simultaneous client connections to itself and supports simultaneous access to multiple Cambrionix units.
Before you can use the Cambrionix Hub API, there are a few steps and checks that need to be completed.
For the Hub API to be able to retrieve USB information from connected devices, it must have direct access to the hardware. This means that in general running in a Virtual Machine (VM) such as Parallels or VirtualBox is not supported as the virtualisation prevents the Hub API from being able to determine which USB device is connected to which physical port. Also, it is not unusual that such a virtual environment will not have access to serial devices which is necessary to chat with the hub to query information.
The Hub API uses JSON-RPC over TCP. Any programming language that has support for JSON-RPC can be used, libraries are widely available for other language.
For macOS an installer is provided that will set up
CambrionixApiService
to run as a daemon process.
The installation can also perform all necessary steps to install and configure Python for the supplied example scripts.
For Windows a self extracting installer is provided that will set up
CambrionixApiService
to run as a Windows service.
The installation can also perform all necessary steps to install and configure Python for the supplied example scripts.
The Linux package comes as a Debian package which you can install either via the GUI or from the command line using apt:
$ sudo apt install ~/Downloads/cambrionix-api-setup-?????????.deb
There is also an armhf version that has been tested on oDroid and Raspberry Pi.
# -–version: Return the version of CambrionixApiService and then exit:
# Example:
$ CambrionixApiService -–version
CambrionixApiService 3.18.0
Copyright 2024 Cambrionix Ltd
http://www.cambrionix.com/
The following values will be returned on exit of
CambrionixApiService
:
CambrionixApiService –-version
).Log messages generated by CambrionixApiService go to syslog.
Some example scripts in Node.JS, C#, VB.Net, and Python are included in with the installed files. For Python, we strongly recommend using the newer asyncio example rather than the older synchronous examples.
%ProgramFiles%\Cambrionix\API\examples
/usr/local/share/cambrionix/apiservice/examples
./Library/Cambrionix/ApiService/examples
.To install the Python async api package go to
examples/python/asyncio
and run
pip install .
Here is a minimal example of using the synchronous Hub API package, the code is written in Python 3.6:
# Import the cbrxapi library.
import sys
from cbrxapi import cbrxapi
print("Querying Hub API Version...")
try:
= cbrxapi.cbrx_apiversion()
result except Exception as e:
print(f"Could not communicate with API : {e}")
= None
result
if result:
print(f"Hub API Version {result[0]}.{result[1]}")
# Call cbrx_discover with "local" to find any locally attached Cambrionix units.
# This will return a list of local Cambrionix units.
print("Discovering local devices..")
= cbrxapi.cbrx_discover("local")
result if not result or len(result) == 0:
print("No Cambrionix unit found.")
0)
sys.exit(
print(f"Discovered {len(result)} units")
for unit_id in result:
= cbrxapi.cbrx_discover_id_to_os_reference(unit_id)
serial_port
try:
# Open a connection to the Cambrionix unit, which will return a handle for
# the connection.
= cbrxapi.cbrx_connection_open(unit_id)
handle except Exception as e:
print(f"Could not open connection to {unit_id} : {e}")
= None
handle
if handle:
# Using the handle, get the "Hardware" and "nrOfPorts" properties
= cbrxapi.cbrx_connection_get(handle, "Hardware")
hardware = cbrxapi.cbrx_connection_get(handle, "nrOfPorts")
n_ports
# Done using the Cambrionix unit, close the handle.
cbrxapi.cbrx_connection_close(handle)
# Finally, print out the information retrieved from the Cambrionix unit.
print(f"* {hardware} on {serial_port} has {n_ports} ports")
And another example demonstrating access from a React application.
Note that the socket connection address is prefixed with
ws
. This allows the Hub API to upgrade the connection to a
Web-socket and be natively used by web technologies such as this. The
same methods can be used from Node.js and other similar platforms.
import React from 'react';
import Websocket from 'react-websocket';
class MyApiInterface extends React.Component {
= 0;
lastId
render() {
return (
<Websocket ref={r => this.websocket = r} reconnect
url="ws://localhost:43424" protocol="jsonrpc"
onMessage={this.onDataReceived.bind(this)}
onOpen={this.onApiConnection.bind(this)}
onClose={this.onApiDisconnection.bind(this)} />
;
)
}
= {};
requests
onDataReceived(json) {
const data = JSON.parse(json);
const id = data.id;
if (id) {
const request = this.requests[id];
if (request && request.callback) {
.callback(data);
request
}delete this.requests[id];
}else
{//Could get a notification here if you enable them on active connection
//Notifications have no id and can arrive at any time
}
}
makeRequest(method, params, callback) {
var packet = {
jsonrpc: "2.0",
id: ++this.lastId,
method: method,
params: params,
;
}
this.requests[packet.id] = {packet: packet, callback: callback};
this.websocket.sendMessage(JSON.stringify(packet));
}
onApiConnection() {
console.log("Connected");
this.makeRequest("cbrx_discover", ["local"], console.log);
}
onApiDisconnection() {
console.log("Disconnected");
this.requests = {}
} }
Connections can be made directly to an http prefixed URI, in which case the json is extracted from either the address itself, or the body content of the GET request. Try this example in your browser now: {“method”:“cbrx_discover”,“params”:[“all”],“jsonrpc”:“2.0”,“id”:1}.
Or from the command line, using curl, you can do:
curl -get http://localhost:43424/?{\"id\":0,\"jsonrpc\":\"2.0\",\"method\":\"cbrx_discover\",\"params\":[\"all\"]}
A JSON-RPC error will return an error member containing the following members:
The Python JSON-RPC used causes an exception for an error response with the following mapping:
In step 3 you could catch an error response with:
try:
= cbrxapi.cbrx_connection_open(id)
handle except jsonrpc.RPCFault as e:
= True
gotException = e.error_code
errorCode = e.error_message
errorMessage = e.error_data errorData
Depending on the errorCode
returned different actions
can be taken, i.e. the user could be prompted to check whether the
device is plugged in before retrying.
The Cambrionix Hub API is implemented in CambrionixApiService, which sits between the application and the Cambrionix units. It maps the properties of the Cambrionix units into Hub API commands.
In its simplest form, it accepts socket connections on
localhost:43424
and subsequent JSON-RPC request
packets to which it will respond. These socket connections may also be
WebSockets.
The descriptions of the Hub API calls contain a sample Python call and the raw jsonrpc requests / responses as you would see them on the wire.
Additionally with API 3.20.0 there is the start of a new http based restful API.
The documentation for this is available from the API itself by visiting The Swagger Documentation
The JSON-RPC implementation should hide these details.
The Python request
cbrxapi.cbrx_connection_get(7654, "nrOfPorts")
translates
into a JSONRPC request containing the method name:
"cbrx_connection_get"
and a JSON representation of the parameters (params
),
which is often a JSON array of values, unless otherwise specified:
[ 7654, "nrOfPorts" ]
Two further key-value pairs need to be passed to complete the JSON-request; One indicating the version of jsonrpc being used, in this case 2.0 and an id identifying this request:
The id is mandatory but only relevant if multiple requests can be outstanding simultaneously over the same connection. It helps to match responses to (asynchronous) requests. The response for a request will be given the matching id by CambrionixApiService. The Hub API Service runs on many threads and there is no guarantee, nor requirement by the specification, that the replies will arrive in any particular order. If strict ordering is required, you can batch multiple request packets in an array which will be ordered the same as it arrived.
Grouping this all together will give the complete JSON-RPC request:
{
"jsonrpc": "2.0",
"method": "cbrx_connection_get",
"params": [
7654,
"nrOfPorts"
],
"id": 0
}
There are 3 groups of calls in the API:
Return the interface version of the local Hub API running.
Input:
or
cbrx_apidetails
. Since true
will be ignored by older APIs, its a simple way to get the extended
version if its available.Returns:
Example Python call:
cbrxapi.cbrx_apiversion()
Example JSONRPC request:
{
"jsonrpc": "2.0",
"method": "cbrx_apiversion",
"id": 0
}
Example successful response:
{
"jsonrpc": "2.0",
"id": 0,
"result": [2, 0]
}
Returns an enhanced version of the details of the API. This information can also be gained by passing an optional true parameter to cbrx_apiversion.
Input:
Returns:
Example Python call:
cbrxapi.cbrx_apidetails()
Example JSONRPC request:
{
"jsonrpc": "2.0",
"method": "cbrx_apidetails",
"id": 0
}
Example successful response:
{
"jsonrpc": "2.0",
"id": 0,
"result": {
"branch": "release",
"capability": [
"protobuf",
"crash-report",
"notification"
],
"bundled": true, // Only if run via LiveViewer bundling
"commitid": 3298696760,
"documentation": "/Library/Cambrionix/ApiService/doc/Cambrionix API Reference.html",
"install": "/Library/Cambrionix/ApiService",
"logging": "/Library/Log/Cambrionix",
"settings": "/Library/Cambrionix/ApiService",
"notifications": [
"usb-changed",
"usb-device-attached",
"usb-device-detached",
"discover-changed",
"dead-hub-changed",
"firmware-progress",
"rfid-received",
"rfid-removed",
"over-temperature",
"over-voltage",
"under-voltage",
],
"semver": "3.1.15+123",
"version": [3, 1, 15, 123]
}
}
This information is made available so that future versions of LiveViewer and API can detect the available features without intimate knowledge of version numbers.
The notification
capability indicates that the
cbrx_notifications method is supported.
The crash-report
capability is internal and should
not be used.
The protobuf
capability is currently internal to the
Hub API and is used to communicate to the Recorder service. The protobuf
message format may be made available at a later date.
Discover Cambrionix units.
Input:
Returns:
Example Python call:
"local") cbrxapi.cbrx_discover(
Example JSONRPC request:
{
"jsonrpc": "2.0",
"method": "cbrx_discover",
"params": ["local"],
"id": 0
}
Example successful response:
{
"jsonrpc": "2.0",
"id": 0,
"result": ["DB0074F5"]
}
Example unsuccessful response:
{
"jsonrpc": "2.0",
"id": 0,
"error": {
"code": -32602,
"message": "Invalid params"
}
}
Map a unit ID for a discovered Cambrionix unit to a device name as used by the OS.
Input:
cbrx_discover
.Returns:
Note: This only makes sense for locally attached Cambrionix units.
Example Python call:
cbrxapi.cbrx_discover_id_to_os_reference(unitId)
Example JSONRPC request:
{
"jsonrpc": "2.0",
"method": "cbrx_discover_id_to_os_reference",
"params": ["DB0074F5"],
"id": 0
}
Example successful response:
{
"jsonrpc": "2.0",
"id": 0,
"result": ["/dev/ttyUSB0"]
}
Example unsuccessful response:
{
"jsonrpc": "2.0",
"id": 0,
"error": {
"code": -32602,
"message": "Invalid params"
}
}
Search for devices attached to local Cambrionix units.
Input:
"<manufacturer-name>\x1D<product-name>\x1D<serial-number>"
.
So for a iPhone, it would be something like
"Apple\x1DiPhone\x1Dfa3c8762e87f068ce16e8c6fa\x1DDevicePath"
.
\x1D
was chosen because it is the ASCII standard character
for a field delimiter and so should be sufficient to avoid false matches
crossing string boundaries. The regex is performed as a search, rather
than a match, so you do not need to do things like
".*iPhone.*"
to match substrings; "iPhone"
is
sufficient. You can of course be as strict as you like. Additionally, if
the phone’s identity or internal serial number have been detected, then
these will also be matched.The regex syntax used is Modified ECMAScript.
Returns:
The returned data is keyed on the serial number of any devices matching the search criteria. The value of each node holds details of the location and the exact device details.
Also note that the entire USB tree is searched for the specified items, and if found anywhere beneath a Cambrionix hub, then the connection details will be returned. This would be especially useful for devices that are plugged into an intermediate hub device rather than being directly connected to the Cambrionix hub, such as a phone with battery extended and extra USB slots.
This new call (as of API 2.1) can save a lot of programmatic work because you no longer need to open each Cambrionix unit individually and check for attached devices. Although, you would of course still need to do that to monitor current draw.
Example Python call:
# Python call to search for all iPhones
"iPhone")
cbrxapi.cbrx_find(
# Regex can be used too
"i(Phone|Pad)")
cbrxapi.cbrx_find(
# Find everything connected to any Cambrionix device
".")
cbrxapi.cbrx_find(
# JSON-RPC call
{"jsonrpc": "2.0",
"method": "cbrx_find",
"params": ["i(Phone|Pad)"],
"id": 1234
}
Example successful response of cbrx_find(‘Super’):
{
"jsonrpc": "2.0",
"id": 1234,
"result": {
"a7cfd7345fad329819cfad3781632ac8a65c": {
"HostDescription": "ThunderSync3-16",
"HostDevice": "0000034CCC2AA16",
"HostPort": 9,
"HostSerial": "COM31",
"Device": {
"VID": 1234
"PID": 5678,
"Manufacturer": "SuperPhone Makers Inc.",
"Description": "SuperPhone6",
"LocationID": 07100000,
"DevicePath": "\\\\?\\usb#vid_1234&pid_5678#08070960a76757#{a5dcbf10-6530-11d2-901f-00c04fb951ed}",
"SerialNumber": "08070960a76757",
"USBVersion": 3,
"USBPower": {
"State": "D0",
"Description": "On"
},
"USBSpeed": {
"Speed": "480Mbps",
"Description": "High"
},
"Endpoints": {
"Active": 4,
"Memory": 16384
}
}
}
}
}
From these results, you could check the status of, for example, the
iPad by running cbrx_connection_open('0000034CCC2AA16')
and then check the status of HostPort by querying cbrx_connection_get(handle, 'PortInfo.9')
.
But if you’re only interested in the presence of devices, then you may
find that you do not need this extra information.
For any search results that do not have their own device serial
number, there will be an additional entry of NoSerial
that
is an array of such results.
For the curious, it may look like unneeded repetition with the serial
numbers, but this is merely because the data here comes from the same
place as the data produced by cbrx_connection_get(handle, 'PortsInfo')
or cbrx_get_usbtree
, and
we’re simply showing everything from the point of connection
upwards.
This method is deprecated in favour of cbrx_get_usb('tree')
. It will
never be removed.
This function allows setting various persistent configuration
options. params
should be an object with key value pairs.
Multiple options may be set at once.
Possible configuration values are:
battery-update-enabled
- Whether battery update queries
are performed. This must be a boolean value (true or false).battery-update-concurrency
- How many concurrent
battery updates will be run simultaneously. The default for this is two
less than the number of processor threads your device has. This must be
an integer value greater than zero.battery-update-frequency-seconds
- How many seconds
between battery updates. The default is 60 seconds. This must be an
integer value greater than zero.{
"jsonrpc": "2.0",
"method": "cbrx_config_set",
"params": {
"battery-update-enabled": true,
"battery-update-concurrency": 2,
"battery-update-frequency-seconds": 60
},
"id": 0
}
This function allows retrieving the configuration options set with cbrx_config_set
.
{
"jsonrpc": "2.0",
"method": "cbrx_config_get",
"params": ["key"],
"id": 0
}
The return value will be as it was set via cbrx_config_set
.
Open a connection to the Cambrionix unit specified. A successful open
results in a connection handle that can be used for further calls to
query information about the hub. This handle should be closed with a
call to cbrx_connection_close
when it is no longer required. An unsuccessful open does not need a
corresponding call to cbrx_connection_close
.
Open handles will automatically expire after 30 seconds
of inactivity. If this occurs, further queries will return
an CBRXAPI_ERRORCODE_INVALIDHANDLE
error.
Input:
cbrx_discover
.Returns:
Example Python call:
# Connect to local device
= cbrxapi.cbrx_connection_open("DB0074F5")
connectionHandle
<!--
# Connect to remote device
= cbrxapi.cbrx_connection_open("EtherSync1d94a0.local.", "remote", "password") connectionHandle
–>
Example JSONRPC request:
{
"jsonrpc": "2.0",
"method": "cbrx_connection_open",
"params": ["DB0074F5"],
"id": 0
}
Example successful response:
{
"jsonrpc": "2.0",
"id": 0,
"result": 7654
}
Example unsuccessful response:
{
"jsonrpc": "2.0",
"id": 0,
"error": {
"code": -10001,
"message": "ID not found"
}
}
Close a connection to a Cambrionix unit previously opened, as specified by the connection handle.
Input parameter:
cbrx_connection_open
.Returns:
Note: It is important to receive the response before closing the socket to ensure the operation has time to be actioned.
Example Python call:
= cbrxapi.cbrx_connection_close(connectionHandle) result
Example JSONRPC request:
{
"jsonrpc": "2.0",
"method": "cbrx_connection_close",
"params": [7654],
"id": 123
}
Example successful response:
{
"jsonrpc": "2.0",
"id": 123,
"result": true
}
Example unsuccessful response:
{
"jsonrpc": "2.0",
"id": 123,
"error": {
"code": -10005,
"message": "Invalid handle"
}
}
List all tags that can return information on the Cambrionix unit specified by connectionHandle.
Input parameter:
cbrx_connection_open
.Returns:
Example Python call:
cbrxapi.cbrx_connection_getdictionary(connectionHandle)
Example JSONRPC request:
{
"jsonrpc": "2.0",
"method": "cbrx_connection_getdictionary",
"params": [7654],
"id": 0
}
Example successful response:
{
"jsonrpc": "2.0",
"id": 0,
"result": [
"SystemTitle",
"Hardware",
"Firmware",
...
]
}
From the Cambrionix unit specified by the connection handle, get the value of the tag.
Input parameters:
connectionHandle
as returned by a previous call to cbrx_connection_open
. Or
the hub’s serial number as returned by cbrx_discover
.propertyName
string. See Get
Dictionary table.Returns:
Example Python call:
= cbrxapi.cbrx_connection_get(connectionHandle, "nrOfPorts") value
Example JSONRPC request:
{
"jsonrpc": "2.0",
"method": "cbrx_connection_get",
"params": [
7654,
"nrOfPorts"
],
"id": 0
}
Example successful response:
{
"jsonrpc": "2.0",
"id": 0,
"result": 8
}
Example unsuccessful response:
{
"jsonrpc": "2.0",
"id": 0,
"error": {
"code": -10003,
"message": "Key not found"
}
}
Like cbrx_connection_get, but instead of a handle takes the hub’s serial number as the initial argument.
Note that this is a convenience function and will almost certainly be slower if you need to do multiple operations on the same hub.
Like cbrx_connection_get, but instead of a handle takes a USB device’s serial number as the initial argument. Only get values that are relevant to ports are accepted.
Note that this is a convenience function and will almost certainly be slower if you need to do multiple operations on the same device.
For example, instead of:
= "123123123123"
deviceSerialNumber = cbrxapi.cbrx_find("iPhone")
allDevices = allDevices[deviceSerialNumber]
myDevice if myDevice:
= cbrxapi.cbrx_connection_open(myDevice["HostDevice"])
handle = cbrxapi.cbrx_connection_get(handle, "PortInfo." + myDevice["HostPort"])
deviceStatus cbrxapi.cbrx_connection_close(handle)
You can use:
= "123123123123"
deviceSerialNumber = cbrxapi.cbrx_device_get(deviceSerialNumber, "PortInfo") deviceStatus
List all writeable value tags and command tags for the Cambrionix
unit specified by connectionHandle
.
Input parameter:
cbrx_connection_open
.Returns:
Example Python call:
cbrxapi.cbrx_connection_setdictionary(connectionHandle)
Example JSONRPC request:
{
"jsonrpc": "2.0",
"method": "cbrx_connection_setdictionary",
"params": [7654],
"id": 0
}
Example successful response:
{
"jsonrpc": "2.0",
"id": 0,
"result": [
"Port.1.mode",
"Port.2.mode",
...
"ClearRebootFlag ",
"Reboot",
...
]
}
On the Cambrionix unit specified by the connection handle, set the tag to the value specified.
Input:
connectionHandle
as returned by a previous call to cbrx_connection_open
.cbrx_connection_setdictionary
.Returns:
Note: It is important to receive the response before closing the socket to ensure the operation has time to be actioned.
Example Python call:
"Reboot", True) cbrxapi.cbrx_connection_set(connectionHandle,
Example JSONRPC request:
{
"jsonrpc": "2.0",
"method": "cbrx_connection_set",
"params": [
7654,
"TwelveVoltRail.OverVoltage",
true
],
"id": 0
}
Example successful response:
{
"jsonrpc": "2.0",
"id": 0,
"result": true
}
Example unsuccessful response:
{
"jsonrpc": "2.0",
"id": 0,
"error": {
"code": -10004,
"message": "Error setting value"
}
}
Like cbrx_connection_set, but instead of a handle takes the hub’s serial number as the initial argument.
Note that this is a convenience function and will almost certainly be slower if you need to do multiple operations on the same hub.
Like cbrx_connection_set, but instead of a handle takes the devices’s serial number as the initial argument.
Also, instead of specifying (for example) Port.N.led1
,
you just specify led1
because the rest is already known
from the context of the device.
For example, instead of:
= "123123123123"
deviceSerialNumber = cbrxapi.cbrx_find("iPhone")
allDevices = allDevices[deviceSerialNumber]
myDevice if myDevice:
= cbrxapi.cbrx_connection_open(myDevice["HostDevice"])
handle if handle:
= cbrxapi.cbrx_connection_set(handle, "Port." + myDevice["HostPort"] ".led1", 255)
deviceStatus cbrxapi.cbrx_connection_close(handle)
You can use:
= "123123123123"
deviceSerialNumber = cbrxapi.cbrx_device_set(deviceSerialNumber, "led1", 255) deviceStatus
Note that this is a convenience function and will almost certainly be slower if you need to do multiple operations on the same hub that are separated by more than a few seconds.
The Hub API supports sending of notifications for certain events.
discover-changed
- The Hub API detected a change in the
available hubs. You should re-run cbrx_discover
at this point.dead-hub-changed
- The Hub API detected that a hub has
either become unresponsive or cannot be connected to, for example
because another program has it’s serial port opened.usb-changed
- The Hub API detected a change in the USB
Tree.usb-device-attached
- More detailed that usb-changed,
this will tell you of specific devices that have arrived.usb-device-detached
- … or detached.firmware-progress
- Request updates on firmware update
progress.rfid-received
- Receive notification when a RFID card
is presented to the sensor on a ModIT Boss.rfid-removed
- Receive notification when an RFID card
is removed from the sensor on a ModIT Boss.all
- Request all notifications.For example, to enable four separate notifications:
{
"jsonrpc": "2.0",
"id": 0,
"method": "cbrx_notifications",
"params": [
"discover-changed",
"usb-device-attached",
"usb-device-detached",
"rfid-received"
]
}
Notification packets are the same as other JSON-RPC packets,
except that they do not have an "id"
field. Most of these
notifications do not supply anything in the "params"
field,
except for the following examples, and the
"firmware-update"
one shown
here.
Example of usb-device-attached
notification (The same
information comes with the "usb-device-detached"
notification.):
{
"jsonrpc": "2.0",
"method": "usb-device-attached",
"params": {
"HostDevice": "1212343456567878",
"HostSerial": "/dev/tty.usbmodem1421502",
"HostPort": 7,
"HostDescription": "PS15-USB3"
"USB2": {
"Description": "iPhone",
"LocationID": 573710336,
"Manufacturer": "Apple Inc.",
"PID": 4776,
"SerialNumber": "012a37d1fa07617ad7ef0430ba49f479ab9fb6b8",
"USBVersion": 2,
"VID": 1452,
},
}
}
Or when an RFID card is scanned on a ModIT Boss.
{
"jsonrpc": "2.0",
"method": "rfid-received",
"params": "1278634123461283764"
}
In this example we show that the device was connected as USB2 only. A USB3 device would have a similar entry. It is presented this way because it is entirely possible to connect (for example) a USB3 device that has its own hub, and USB2 devices. These would be individually shown because they can’t reliably be mixed; you can have hardware entities with the same VID/PID/Serial in sibling trees.
Note: Notifications are only sent to active socket connections that have requested them. Closing a socket and opening another one will mean you need to re-request notifications. See the examples/nodejs folder (installed with the API) for ideas about handling notifications in your code
The firmware functions can control all aspects of updating the firmware on Cambrionix hubs.
There are several sub-commands here that allow you to add or remove firmware files from the API’s local storage, list the currently available firmware files, update firmware from provided files and check the status of existing firmware updates.
Adding firmware files is done by providing a Base64 encoded zip of the file. Encoding is necessary because the JSON packet cannot deal with binary data because it would terminate at any nul characters.
# Example of adding new firmware
# This merely provides it to the Hub API as an available update source
# It does not affect any connected hubs
= myReadFileFunction("SomeCambrionixFirmwareFile.enfir")
rawBytes = base64.b64encode(zip(rawBytes))
encodedBytes "add", "SomeCambrionixFirmwareFile.enfir", encodedBytes) cbrxapi.cbrx_firmware(
# Example of removing firmware from Hub API storage
"remove", "CambrionixFirmware-un") cbrxapi.cbrx_firmware(
# Example of listing available firmware files
list = cbrxapi.cbrx_firmware("list")
print(list)
# Would give something like:
# [
# {filename: "CambrionixFirmware-un", version: "1.79"},
# {filename: "AnotherFirmwareFile-un", version: "1.78"}
# ]
Instruct the Hub API to initiate firmware update on a specific hub. Multiple hubs may be updated simultaneously by issuing the same command per hub. The API will deal with rebooting hubs in the correct order when they are chained.
# Example of starting firmware update (in this case the charger firmware)
# Other types of firmware can be available for different products,
# such as "display" for hubs with more complex LED arrangements.
# Firmware updates can either be specified with a single file,
# or an object of files keyed on the type of firmware update.
= cbrxapi.cbrx_connection_open("1212343456567878")
handle
# For example, update all firmware for selected device from the firmware files provided.
"update", handle, {"un": "CambrionixFirmware-un", "mc": "MotorControlFirmware-mc"}) cbrxapi.cbrx_firmware(
New in 3.9.0, you can also use the serial number directly instead of the handle.
# Initiate firmware update for hub by serial number
cbrxapi.cbrx_firmware("update", "1212343456567878", {"un": "CambrionixFirmware-un", "mc": "MotorControlFirmware-mc"})
# Example of getting status of firmware update
"status", handle) cbrxapi.cbrx_firmware(
Could give:
{
"Version": "1.88.0", // Only present after initialising stage
"PreviousVersion": "1.79", // Only present after initialising stage
"Type": "charger",
"Progress": 60, // Percent progress
"Stage": "updating",
"HostDevice": "COM3",
"HostSerial": "1212343456567878",
"HostDescription": "SuperSync15",
"Started": 123123123123, // UTC time of start
"Ended": 123123123123 // UTC time of end time (only when status is complete)
}
An option “Error” field will be set if there was an issue at a particular stage.
"connecting"
, "initialising"
,
"erasing"
, "updating"
,
"verifying"
, "complete"
,
"rebooted"
, "skipped"
An error during "initialising"
will usually mean the
wrong type of firmware was used for the selected device. For example, a
firmware file suffixed with -ps
is specifically for a
PD-Sync, whereas suffixes of -un
are for PowerPad,
SuperSync, ThunderSync and ModIT style hubs.
All other errors after this stage would likely mean that the hub’s firmware is now in an invalid state and would need to be re-done.
Note that this is not possible with the python implementation that we provide because it creates a new socket per message and immediately closes it. This will change in the future when we provide more object oriented native language layers to talk to the API.
Retrieve previous firmware update results since the Hub API was running for any device.
# Example of getting status of firmware update
"history", handle)
cbrxapi.cbrx_firmware(
# Could give:
# {
# "un": {
# Version: "1.79",
# Type: "display",
# Progress: 60,
# Stage: "flashing"
# }
# }
The return value is keyed by the firmware type that was updated and includes the same results as the status command.
In addition to the status request option, you can also listen for
notifications on the same socket that initiated the firmware update.
These notifications would be JSON-RPC packets
without an "id"
field. And would have a “params” field with
the details of the progress. These notifications will only be sent if
they are enabled using the cbrx_notifications([“firmware-progress”])
method.
Example notification packet:
{
"jsonrpc": "2.0",
"method": "firmware-progress",
"params": {
"Progress": 60,
"Stage": "flashing",
"Type": "charger",
"HostDevice": "1212343456567878",
"HostSerial": "/dev/tty.usbmodem1421502",
"HostDescription": "PS15-USB3"
}
}
This method is used in the new LiveViewer™ application to show firmware update progress.
Forcibly close all connections to a Cambrionix unit and lock it
against further use until released by cbrx_connection_unlock
.
Other processes that were using these connections will receive a
CBRXAPI_ERRORCODE_LOCKED
error if trying to access this
Cambrionix unit. Locking a Cambrionix unit that was not previously
opened does no harm and will succeed.
Input parameter:
Returns:
Note: It is important to receive the response before closing the socket to ensure the operation has time to be actioned.
Example Python call:
"DB0074F5") cbrxapi.cbrx_connection_closeandlock(
Example JSONRPC request:
{
"jsonrpc": "2.0",
"method": "cbrx_connection_closeandlock",
"params": ["DB0074F5"],
"id": 0
}
Example successful response:
{
"jsonrpc": "2.0",
"id": 0,
"result": true
}
Example unsuccessful response:
{
"jsonrpc": "2.0",
"id": 0,
"error": {
"code": -10001,
"message": "ID not found"
}
}
Unlock a Cambrionix unit that was previously locked with cbrx_connection_closeandlock
.
Unlocking a Cambrionix unit that was not previously locked does no harm
and will succeed.
Input parameter:
Returns:
Note: It is important to receive the response before closing the socket to ensure the operation has time to be actioned.
Example Python call:
"DB0074F5") cbrxapi.cbrx_connection_unlock(
Example JSONRPC request
{
"jsonrpc": "2.0",
"method": "cbrx_connection_unlock",
"params": ["DB0074F5"],
"id": 0
}
Example successful response:
{
"jsonrpc": "2.0",
"id": 0,
"result": true
}
Example unsuccessful response:
{
"jsonrpc": "2.0",
"id": 0,
"error": {
"code": -10001,
"message": "ID not found"
}
}
Perform command line interface operation on the connected hub and return the complete result. This allows you to run commands directly on the hub’s command line without stopping the Hub API service, connecting to the serial port and so on.
The return is an array of strings containing all the lines of output returned from the command.
7654, "id") cbrxapi.cbrx_connection_cli(
Example JSONRPC request
{
"jsonrpc": "2.0",
"method": "cbrx_connection_cli",
"params": [7654, "id"],
"id": 1337
}
Example successful response:
{
"jsonrpc": "2.0",
"id": 1337,
"result": [
"mfr:cambrionix,mode:main,hw:PP15S,hwid:0x13,fw:1.83,bl:0.12,sn:000000,group:-,fc:un"
]
}
Initiate pairing of an iOS device. This is not usually necessary as it will occur automatically when the Hub API attempts to query battery information.
In both examples here, "UDID"
is the phone’s USB serial
number.
"UDID") cbrxapi.cbrx_pair_device(
Example JSONRPC request
{
"jsonrpc": "2.0",
"method": "cbrx_pair_device",
"params": ["UDID"],
"id": 1337
}
Supply (or remove) a certificate and private key to the Hub API to
allow SSL connections from outside of localhost
(the
machine the Hub API is running on). Without this certificate, the Hub
API will only listen for connections on localhost:43424
.
Once a valid certificate and private key are provided, this will change
to 0.0.0.0:43424
. External connections (not from
localhost
) will only be allowed if they are SSL connections
(HTTPS or Secure WebSockets).
It is up to the user to supply a certificate that is suitable for their usage. For example, if it is not signed by a certificate authority, then you will need to deal with this in the usual way, such as signing your certificate with your own certificate autority and adding that to your application or browser. With Google Chrome you can use this guide. There are similar guides for other browsers.
Only a single certificate configuration is supported.
If a password is supplied, it is obfuscated to avoid prying eyes.
To add a certificate and private key to the API:
{
"id": 1234,
"jsonrpc": "2.0",
"method": "cbrx_certificate",
"params": [
"set",
{
"private-key": <private key filename>,
"certificate": <certificate filename>,
"password": <optional password if required by private key>
}
]
}
Remove the certificate and private from the API:
{
"id": 1234,
"jsonrpc": "2.0",
"method": "cbrx_certificate",
"params": [
"remove"
]
}
First parameter describes the information to fetch. * tree - Psynonym for cbrx_get_usbtree. * descriptors - Get all USB descriptor information from a single USB node.
Return the entire USB tree that has been discovered.
Returns:
The returned data can be quite large if you have a lot of connected devices, but can be easily printed using the cbrx_usbtree.py example. Or just view as JSON from a browser request such as: cbrx_get_usb(‘tree’)
Example Python call:
# Example output from cbrx_usbtree.py example
'Description': 'Intel(R) USB 3.20 eXtensible Host Controller - 1.20 (Microsoft)',
[{'HostController': {'EndpointMemoryUsed': 0x25000, 'EndpointPeakMemoryUsed': 0x9b000, 'EndpointPeakTotal': 0x007d, 'EndpointTotal': 0x0021, 'Type': 'XHCI'},
'LocationID': 0x21000000,
'PID': 0x7ae0,
'SerialNumber': '3&11583659&0&a0',
'USBSpeed': {'Description': 'SuperSpeed USB 20Gbps', 'Speed': '20Gbps'},
'USBVersion': 3.2,
'VID': 0x8086},
'Description': 'TS3-C10',
{'LocationID': 0x23000000,
'Manufacturer': 'Cambrionix',
'PID': 0x15d3,
'SerialNumber': 'a-2aa5366c-0-2',
'USBSpeed': {'Description': 'SuperSpeed USB 5Gbps', 'Speed': '5Gbps'},
'USBVersion': 3.0,
'VID': 0x8086,
'children': [{'Description': 'Fresco Logic USB 3.0 eXtensible Host Controller - 1.0 (Microsoft)',
'HostController': {'EndpointMemoryUsed': 0x18000, 'EndpointTotal': 12, 'Type': 'XHCI'},
'LocationID': 0x23000000,
'PID': 9,
'SerialNumber': 'c&2d6c3950&0&0000000800e4',
'USBSpeed': {'Description': 'SuperSpeed USB 5Gbps', 'Speed': '5Gbps'},
'USBVersion': 3.0,
'VID': 0xca3b},
'Description': 'Fresco Logic USB 3.0 eXtensible Host Controller - 1.0 (Microsoft)',
{'HostController': {'EndpointMemoryUsed': 0, 'EndpointTotal': 6, 'Type': 'XHCI'},
'LocationID': 0x24000000,
'PID': 10,
'SerialNumber': 'c&2cc681d1&0&0008000800e4',
'USBSpeed': {'Description': 'SuperSpeed USB 5Gbps', 'Speed': '5Gbps'},
'USBVersion': 3.0,
'VID': 0xca3b,
'children': [{'Description': 'Ultra USB 3.0',
'Endpoints': {'Active': 3, 'Memory': 0x6000},
'FlashDrive': {'Available': 0x1f2378000, 'Capacity': 0x1fffff000, 'Path': 'D:\'
'LocationID': 0x24300000,
'Manufacturer': 'SanDisk',
'PID': 0x5595,
'SerialNumber': '4C530000131105120260',
'USBPower': {'Description': 'On', 'State': 'D0'},
'USBSpeed': {'Description': 'SuperSpeed USB 5Gbps', 'Speed': '5Gbps'},
'USBVersion': 3.0,
'VID': 0x0781}]},
'Description': 'Fresco Logic USB 3.0 eXtensible Host Controller - 1.0 (Microsoft)',
{'HostController': {'EndpointMemoryUsed': 0, 'EndpointTotal': 3, 'Type': 'XHCI'},
'LocationID': 0x25000000,
'PID': 11,
'SerialNumber': 'c&1601d69&0&0010000800e4',
'USBSpeed': {'Description': 'SuperSpeed USB 5Gbps', 'Speed': '5Gbps'},
'USBVersion': 3.0,
'VID': 0xca3b,
'children': [{'Description': 'TS3-C10',
'Endpoints': {'Active': 3, 'Memory': 0x3000},
'LocationID': 0x25200000,
'Manufacturer': 'Cambrionix',
'PID': 0x6015,
'SerialNumber': 'a-2aa5366c-0-2',
'USBPower': {'Description': 'On', 'State': 'D0'},
'USBSpeed': {'Description': 'Full', 'Speed': '12Mbps'},
'USBVersion': 2.0,
'VID': 0x0403,
'VirtualSerialPort': 'COM25'}]}]}]
Request entire dump of a USB device’s descriptor information. USB Descriptors define the behaviour and capabilities of a USB device and are present for all USB devices.
This can be a lot of data for some devices (especially phones and tablets), so we won’t go into the details of it here. All variable names in the returned data match the names in Chapter 9 of the USB 3.2 specification for ease of reference.
A small example is shown here, however some devices can have very many configurations and descriptors.
An additional argument may be provided to output an additional
RawBytes
member for each descriptor (except for string
descriptors). This output can either be hex or base64 encoded by
specifying "hex"
or "base64"
.
Each descriptors raw fields (as taken from the USB 3.2 spec) are
represented first, and where appropriate an additional
"Derived"
member will be present that shows bitfields or
resolved string descriptors. For example, on the device’s main
descriptor there is an iManufacturer
field, which is the
index of the string descriptor used for that name. This will also be
present in Derived.Manufacturer
.
{
"jsonrpc": "2.0",
"method": "cbrx_get_usb",
"params": ["descriptors", "123456789abcdef"],
"id": 1337
}
Output from a standard USB flash drive:
{
"jsonrpc": "2.0",
"id": 0,
"result": {
"RawBytes": "120120030000000951092b17010001020301",
"bLength": 18,
"bDescriptorType": 1,
"bNumConfigurations": 1,
"bcdUSB": 800,
"bDeviceClass": 0,
"bDeviceSubClass": 0,
"bDeviceProtocol": 0,
"bMaxPacketSize0": 9,
"idVendor": 2385,
"idProduct": 5931,
"bcdDevice": 1,
"iManufacturer": 1,
"iProduct": 2,
"iSerialNumber": 3,
"Derived": {
"DescriptorType": "Device",
"CurrentConfiguration": 1,
"DeviceClass": "Reserved"
},
"Configurations": {
"1": [
{
"RawBytes": "09022c00010100ff8025",
"bLength": 9,
"bDescriptorType": 2,
"wTotalLength": 44,
"bConfigurationValue": 1,
"bmAttributes": 128,
"bNumDescriptors": 1,
"iConfiguration": 0,
"reserved1": 0,
"reserved2": 1,
"SelfPowered": 0,
"Derived": {
"DescriptorType": "Configuration",
"MaxPower": 37,
"RemoteWakeUp": 0,
"BusPowered": 0
}
},
{
"RawBytes": "090400000208065000",
"bLength": 9,
"bDescriptorType": 4,
"iInterface": 0,
"bInterfaceNumber": 0,
"bAlternateSetting": 0,
"bNumEndpoints": 2,
"bInterfaceClass": 8,
"bInterfaceSubClass": 6,
"bInterfaceProtocol": 80,
"Derived": {
"DescriptorType": "Interface"
}
},
{
"RawBytes": "0705ff8102000400",
"bLength": 7,
"bDescriptorType": 5,
"bInterval": 0,
"bEndpointAddress": 129,
"bmAttributes": 2,
"wMaxPacketSize": 1024,
"Derived": {
"DescriptorType": "Endpoint",
"EndpointAddress": 1,
"Direction": "In",
"Type": "Bulk"
}
},
{
"RawBytes": "06300f000000",
"bLength": 6,
"bDescriptorType": 48,
"wBytesPerInterval": 0,
"bMaxBurst": 15,
"bmAttributes": 0,
"Derived": {
"DescriptorType": "SuperSpeedEndpointCompanion",
"MaxStreams": 0,
"Mult": 0,
"SspCompanion": 0
}
},
{
"RawBytes": "07050202000400",
"bLength": 7,
"bDescriptorType": 5,
"bInterval": 0,
"bEndpointAddress": 2,
"bmAttributes": 2,
"wMaxPacketSize": 1024,
"Derived": {
"DescriptorType": "Endpoint",
"EndpointAddress": 2,
"Direction": "Out",
"Type": "Bulk"
}
},
{
"RawBytes": "06300f000000",
"bLength": 6,
"bDescriptorType": 48,
"wBytesPerInterval": 0,
"bMaxBurst": 15,
"bmAttributes": 0,
"Derived": {
"DescriptorType": "SuperSpeedEndpointCompanion",
"MaxStreams": 0,
"Mult": 0,
"SspCompanion": 0
}
}
]
},
"Strings": {
"1": "Kingston",
"2": "DataTraveler 70",
"3": "1831BFBD3065F551C96001E7"
},
"BOS": {
"RawBytes": "050f160002",
"bLength": 5,
"bDescriptorType": 15,
"Derived": {
"DescriptorType": "BOS"
},
"wTotalLength": 22,
"bNumDescriptors": 2,
"Capabilities": [
{
"RawBytes": "07100206000000",
"bLength": 7,
"bDescriptorType": 16,
"bDevCapabilityType": 2,
"bmAttributes": 6,
"Derived": {
"DescriptorType": "DeviceCapability",
"CapabilityType": "USB20Extension",
"LPMCapable": 1,
"BESLAndAlternateHIRDSupported": 1,
"BaselineBESLValid": 0,
"DeepBESLValid": 0,
"BaselineBESL": 0,
"DeepBESL": 0
}
},
{
"RawBytes": "0a1003000e00020affff07",
"bLength": 10,
"bDescriptorType": 16,
"bDevCapabilityType": 3,
"wU2DevExitLat": 2047,
"bmAttributes": 0,
"wSpeedsSupported": 14,
"bFunctionalitySupport": 2,
"bU1DevExitLat": 10,
"Derived": {
"DescriptorType": "DeviceCapability",
"CapabilityType": "SuperSpeedUSB",
"LTMCapable": 0,
"SpeedsSupported": [
"Full",
"High",
"SuperSpeed"
]
}
}
]
}
}
}
Local and remote Cambrionix units need to be treated slightly differently due to the way they are accessed.
A local
Cambrionix unit is one that is connected with a
USB cable to the machine which is running the API. If you do not specify
the location to cbrx_discover
or cbrx_connection_open
then the Hub API will assume that you are using a local Cambrionix
unit.
A remote
Cambrionix unit is not connected to the machine
which is running the Hub API but is instead connected to a network that
is accessible from the machine which is running the Hub API. Currently
the only Cambrionix unit which connects over a network is the
EtherSync.
In order to connect to a remote Cambrionix unit you must discover it
first by passing "remote"
as the location parameter to cbrx_discover
. You can then call
the cbrx_connection_open
specifying the device ID of the remote unit as well as
"remote"
for the location with an additional parameter of
the password for the unit (this is printed on the bottom of the
EtherSync device). Once the connection is open the handle is sufficient
for the Hub API to distinguish local or remote and so other calls do not
need to specify the location.
The U8S and U8S-EXT chargers have a small difference from other Cambrionix Universal Chargers in that their control or update port has an external connection. All other Cambrionix Universal Chargers have a single host connection that combines the functions of the upstream connection to the host with the control or update port.
In order for the U8S or U8S-EXT to work correctly with the Hub API there must be a USB cable that connects the control or update port to an expansion port on the same board. This is in addition to the USB cable that connects the host port to the machine running the Hub API.
When there are two Cambrionix chargers that have been built into a
product, with the second charger connected to an expansion port of the
first charger, this is known as a Dock
. For some operations
it may be convenient to treat these two chargers as a single unit, that
combines the ports of both chargers.
If the application wishes to access the dock as a single unit it
should firstly call cbrx_discover
with the parameter
docks
to obtain the list of docks available. The
application should then call cbrx_connection_open
with
the ID in question and also specifying "docks"
.
The dock unit will return the combined total for tags such as
nrOfPorts
and TotalCurrent_mA
. The range of
ports is expanded to cover the combined total number of ports for the
two chargers. For the charger with its host port directly connected to
the computer, its ports will be referenced first followed by those of
the charger connected to first charger’s expansion port. e.g. if a U16S
has its host port connected to the host computer and an expansion port
connects to a U8S, port 11 will be port 11 on the U16S and port 23 will
be port 7 on the U8S.
It is also necessary to install jumpers on the parent and child
boards. These jumpers are used to set the Group ID
. The
parent board must have a Group ID
of 8
i.e. a
jumper installed on the pair of pins marked 8
. The child
board must have a Group ID
of 8 + 1
i.e. two
jumpers, one jumper on the pair of pins marked 8
and one
jumper on the pair of pins marked 1
. No other jumpers
should be installed on the Group ID
block of pins.
Some tags such as Hardware
or Firmware
do
not combine in a meaningful way and so these tags will return the value
for the parent charger. If it is desired to get the values of these tags
from the downstream charger then it is possible to open and retrieve
them from that charger in the usual manner. Opening a charger does not
interfere with access to the dock except as to when settings are
changed.
Calls to cbrx_connection_set
for a
dock will result in the relevant tag being set on both the chargers
except for the port specific tags which will be directed to the
appropriate charger only.
Entirely at your discretion, you can open a pseudo hub that is a combination of various other hubs. This behaves in the same way that Docks hubs do, as detailed above.
To open a dynamic hub, simple combine the serial numbers of all the
hubs you wish to open into a special "Dynamic:"
prefixed
name as shown in this example.
# Given three Cambrionix hubs with serial numbers of 'AAAA', 'BBBB' and 'CCCC'
= cbrxapi.cbrx_connection_open("AAAA")
handleA = cbrxapi.cbrx_connection_open("BBBB")
handleB = cbrxapi.cbrx_connection_open("CCCC")
handleC = cbrxapi.cbrx_connection_open("Dynamic:AAAA:BBBB:CCCC")
handleABC
print(cbrxapi.cbrx_connection_get(handleA, "nrOfPorts")) # 15
print(cbrxapi.cbrx_connection_get(handleB, "nrOfPorts")) # 8
print(cbrxapi.cbrx_connection_get(handleC, "nrOfPorts")) # 8
print(cbrxapi.cbrx_connection_get(handleABC, "nrOfPorts")) # 31
This dynamic hub is treated as a single entity with it’s ports being numbered from 1 to N, where N is the total number of ports across all hubs included.
For each Cambrionix unit, the Hub API can return two dictionaries:
Get dictionary
, containing keys for the tags that
can be read.Set dictionary
, containing keys for the tags that
can be written to or can perform an action.The keys returned depend on the feature set(s) supported by the unit.
The following feature sets are available:
Feature set | Description |
---|---|
base | Base level functionality supported by all Cambrionix units |
sync | Syncing capability |
5V | The unit has a fixed 5V power supply |
12V | The unit has a 12v power supply |
temperature | The unit has a temperature sensor |
PD | The unit implements the USB Power Delivery Specification |
gate | The unit has a motor control board to control locking gates to protect phones from removal. |
All Cambrionix units support the base
feature set.
The range of possible values for a tag in the base
feature set can be extended if an additional feature set is also
available. For example, Port.n.flags
can only return a flag
S
(port is in Sync mode) on a device that also implements
the sync
feature set.
The Hardware
key returns a value for the type of
Cambrionix unit.
These are the extra feature sets CambrionixApiService
supports for the various types of Cambrionix unit:
Cambrionix unit type returned by “Hardware” | sync | 5V | 12V | Temperature | PD | gate |
---|---|---|---|---|---|---|
PP8C | yes | yes | yes | |||
PP8S | yes | yes | yes | yes | ||
PP15C | yes | yes | yes | |||
PP15S | yes | yes | yes | yes | ||
PS15 | yes | yes | yes | yes | ||
Series8 | yes | |||||
U8C-EXT | yes | yes | yes | |||
U8C | yes | |||||
U8RA | yes | yes | ||||
U8S-EXT | yes | yes | yes | yes | ||
U8S | yes | yes | ||||
U10C | yes | |||||
U10S | yes | yes | ||||
U12S | yes | yes | ||||
U16S-NL | yes | yes | ||||
PD-Sync 4 | yes1 | yes | yes | |||
ThunderSync | yes | yes | yes | |||
ThunderSync3-16 | yes | yes | yes | |||
ModIT Pro2 | yes | yes | yes | yes | ||
ThunderSync3-C10 | yes1 | yes | yes |
1 It is to be noted that while the chargers with TypeC connections are always in sync mode unless the ports are turned off. This means that there is no need to switch between charge mode and sync mode.
2 The ModIT Pro will identify itself as a ThunderSync3-16, but it has additional hardware for gate control.
A bit-field with one bit set for each port with a device attached, port 1 in bit 0, port 2 in bit 1 and so on.
Example return value:
7
Timestamp of firmware version.
Example return value:
"Jul 08 2015 10:43:20"
List of global profiles currently enabled
Example return value:
"1 2 3 4"
Get the endpoint memory being used by a hub.
This is broken down into several sections:
self
- The endpoint count and memory being used by the
hub itself.ports
- The endpoint count and memory being used by the
devices connected to the hub.self-with-ports
- A combination of self and ports.self-with-ports-recursive
- A combination of
self-with-ports, plus the totals from any chained hubs and devices below
this node.Request:
{
"jsonrpc": "2.0",
"id": 1,
"method": "cbrx_hub_get",
"params": [
"hub-serial-number",
"EndpointUsage"
]
}
Firmware version string
Example return value:
"1.55"
Get the types of Firmware applicable to this hub, returned as an array containing information for all types of firmware that the hub accepts. For each entry, the FormFactor field indicates the firmware type for that part, which can be one of “un”, “ps”, “pd” for mainboard firmware, “db” for LED firmware or “mc” for Motor Control Board.
Returns an array of information about each type of firmware currently installed, with details of the firmware types required to update them.
Example return value:
[
{
"Bootloader": "0.13",
"Firmware": "1.83",
"FormFactor": "un",
"Group": "-",
"Hardware": "PP15",
"Manufacturer": "cambrionix",
"PanelID": 0,
"SerialNumber": "DN004ANJ"
}
]
Returns list of 5V supply rail error flags that have been detected, if any.
Example return value:
""
Upper limit of the 5V rail that will trigger the error flag.
Example return value:
5.58
Lower limit of the 5V rail that will trigger the error flag
Example return value:
3.5
Current 5V supply voltage in Volt (V)
Example return value:
5.25
Highest 5V supply voltage seen in Volt (V)
Example return value:
5.25
Lowest 5V supply voltage seen in Volt (V)
Example return value:
5.2
Returns an object describing the states of all gates on the expansion board if present. Currently, this is only available on the ModIT range.
Example return value:
{
"1": "open",
"2": "closed",
"3": "closing",
"4": "opening"
}
Group letter read from PCB jumpers, or “–” if no group jumper was fitted.
Example return value:
"-"
Type of the Cambrionix unit such as “U8S-EXT”, “PP15”, “PS15-USB3”, “ThunderSync3-16”.
Example return value:
"ThunderSync3-16"
Flags indicating whether features are present
Example return value:
"SLET"
Static information related to the hub. This is fixed information, such as dimensions, web page, or port connector types.
Example return value:
{
"jsonrpc": "2.0",
"id": 1,
"result": {
"ProductName": "ThunderSync3-C10",
"ProductWebPage": "https://www.cambrionix.com/products/thundersync3-c10",
"TemperatureRangeC": {
"Min": 10,
"Max": 35
},
"HumidityRange": {
"Min": 5,
"Max": 95
},
"DimensionsMillimetres": {
"Width": 136,
"Length": 193,
"Height": 34
},
"HostPortType": "Thunderbolt 3",
"HostPortBandwidth": "40Gbps",
"HubMaxPowerOutputWatts": 150,
"Ports": {
"1": {
"HardwareInformation": {
"Type": "USB Type-C",
"Bandwidth": "5Gbps",
"VoltageMax": 5.2,
"MilliampsMax": 3000
}
},
// etc for each port
}
}
}
All available keys that are not port specific and change dynamically, as a dictionary.
Host is connected to the Cambrionix unit
Example return value:
true
List of input rail error flags if any are set.
Example return value:
"OV UV"
Upper limit of the input rail that will trigger the error flag
Example return value:
24.7
Lower limit of the input rail that will trigger the error flag.
Example return value:
9.59
Current input rail supply in Volts (V).
Example return value:
24.03
Highest input voltage seen in Volts (V).
Example return value:
24.14
Lowest input voltage seen in Volts (V).
Example return value:
23.82
0 if button n
has not been pressed since the last time
this entry was read. 1 if button n has been pressed since the last time
this entry was read. Double-clicks cannot be detected.
Example return value:
0
Mode change from Charge to Sync is automatic.
Example return value:
true
Number of USB ports on the Cambrionix unit.
Example return value:
8
PanelID number of front panel board, if fitted, or “Absent”/“None”.
Example return value:
"Absent"
If possible, retrieve the current battery level of the connected device. See notes about battery information collection. Depending on the device type (Android, iOS etc.) and the host OS, different data may be returned.
Example return value:
{
"CurrentLevel": 78,
"CurrentTime": 15234254346,
"StartLevel": 23,
"StartTime": 15124151512,
}
Note that battery information may only be available after a device is paired or trusted with the host computer. If this does not occur automatically, you can use cbrx_pair_device(UDID). Where UDID is the USB serial number of the device.
Current being delivered to the USB device connected to this USB port in milli-Amperes (mA).
Example return value:
0
Description as reported by the USB device attached to this USB port if it could be detected. Empty string is returned if it could not be detected.
Example return value:
"SuperPhone6"
Energy the USB device on this USB port has consumed in Watt-hours (calculated every second).
Example return value:
0.0
If detected, returns the mount point of a USB flash drive. For Windows this will be a drive letter, otherwise it will be a volume mount point.
As of Hub API version 3.10.0, the addition of the
"Volumes"
field will list all the volumes of the drive in
addition to the first discovered volume prior to 3.10.0.
Example return values:
# Windows
{
"Path:": "H:\\",
"Capacity": 123123123,
"Available": 123123,
"Volumes": [
{
"Path:": "H:\\",
"Capacity": 123123123,
"Available": 123123,
"Label": "Volume Label 1",
"Index": 1,
"FileSystem": "exFAT"
},
{
"Path:": "I:\\",
"Capacity": 123123123,
"Available": 123123,
"Label": "Volume Label 2",
"Index": 2,
"FileSystem": "NTFS"
}
]
}
# macOS
{
"Path:": "/Volumes/Volume\ Label\ 1",
"Capacity": 123123123,
"Available": 123123,
"Volumes": [
{
"Path:": "/Volumes/Volume\ Label\ 1",
"Capacity": 123123123,
"Available": 123123,
"Label": "Volume Label 1",
"Index": 1,
"FileSystem": "exFAT"
},
{
"Path:": "/Volumes/Volume\ Label\ 2",
"Capacity": 123123123,
"Available": 123123,
"Label": "Volume Label 2",
"Index": 2,
"FileSystem": "NTFS"
}
]
}
# Linux
{
"Path:": "/media/bob/Volume\ Label\ 1",
"Capacity": 123123123,
"Available": 123123,
"Volumes": [
{
"Path:": "/media/bob/Volume\ Label\ 1",
"Capacity": 123123123,
"Available": 123123,
"Label": "Volume Label 1",
"Index": 1,
"FileSystem": "exFAT"
},
{
"Path:": "/media/bob/Volume\ Label\ 2",
"Capacity": 123123123,
"Available": 123123,
"Label": "Volume Label 2",
"Index": 2,
"FileSystem": "NTFS"
}
]
}
If there is no flash drive, the return value will simply be
false
.
This same information will also be provided in PortsInfo, PortInfo.N or cbrx_discover('all')
in a
"FlashDrive"
field where applicable and present. If not
applicable or preset, this field will be absent.
Return the location ID for a specific port. This does not require a device to be attached and so may be used to uniquely identify a USB slot.
Note that for USB3 hubs, this location ID will be different when a USB3 device is plugged in compared to a USB2 device.
Location IDs indicate the bus number that a USB host controller is on in the first byte, then the port numbers down the tree for child devices.
Example return values (shown in hex as it makes more sense that way):
# Bus 21, port 2, port 1
0x21210000
# In this case, the parent hub for the device would be 0x21200000.
Current port mode, using the same characters that #set-port.n.mode will use them to change the mode.
For Standard USB hubs, the mode can be any of:
For Type-C hubs, the mode can be:
Port flags separated by spaces.
Example return value:
"R D S"
Manufacturer as reported by the USB device attached to this USB port, if it could be detected. Empty string is returned if it could not be detected.
Example return value:
"SuperPhone Makers Inc."
Product ID of the USB device attached to this USB port, if it could be detected. 0 (zero) is returned if it could not be detected.
Example return value:
0
Profile ID number, or 0 if not charging.
Example return value:
0
List of enabled profiles for this port.
Example return value:
"1 2 3 4"
Serial number as reported by the USB device attached to this USB port, if it could be detected. Empty string is returned if it could not be detected.
Example return value:
"1127dfa9037s1a8cb1"
Time in seconds since this USB port detected the device has completed charging. -1 will be returned if this port has not detected completed charging.
Example return value:
-1
Or a number of seconds since charging completed.
Time in seconds since this USB port started charging an attached device. 0 will be returned if the USB port has not started charging an attached device.
Example return value:
0
A dictionary containing the values for “Manufacturer”, “Description” and “SerialNumber” for this USB port.
Example return value:
{"SerialNumber": "23213dfe12e2412",
"Description": "SuperPhone6",
"Manufacturer": "SuperPhone Makers Inc."
}
Vendor ID of the USB device attached to this USB port, if it could be detected. 0 (zero) is returned if it could not be detected.
Example return value:
0
Voltage being supplied to the port in 10mV.
Example return value:
520
Retreives an object containing port location IDs for the entire hub.
The advantage over port info is that no device needs to be connectd to a port to know beforehand which location IDs would be valid for the slot.
This request:
{
"id": 5,
"jsonrpc": "2.0",
"method": "cbrx_connection_get",
"params": [
handle,
"Port.all.LocationID"
]
}
Could produce:
{
"jsonrpc": "2.0",
"id": 5,
"result": {
"1": {
"USB2": 591466496,
"USB3": 3812691968
},
"2": {
"Current": 591470592,
"USB2": 591470592,
"USB3": 3812696064
},
"3": {
"USB2": 591597568,
"USB3": 3812823040
},
"4": {
"Current": 591601664,
"USB2": 591601664,
"USB3": 3812827136
}
}
}
And for the same hub, this request:
{
"id": 5,
"jsonrpc": "2.0",
"method": "cbrx_connection_get",
"params": [
handle,
"Port.all.LocationID",
"USB2"
]
}
Could produce:
{
"jsonrpc": "2.0",
"id": 5,
"result": {
"1": 591466496,
"2": 591470592,
"3": 591597568,
"4": 591601664
}
}
Get all port information for specified port.
All available keys and values for this port as a dictionary.
Get all port information for all ports.
All available information for all ports as a dictionary of dictionaries.
Trimmed example of information returned by cbrx_connection_get('PortsInfo')
if a device was connected to port 1. Most of these values can be queried
individually such as Port.1.SerialNumber
or
Port.1.Current_mA
for
example.
{
"Port.1": {
"Port": 1,
"Current_mA": 22,
"Flags": "R A S",
"LocationID": 591470592,
"USBVersion": 2.0,
"VID": 1452,
"PID": 4779,
"Manufacturer": "SuperPhone Makers Inc.",
"Description": "SuperPad",
"SerialNumber": "c13d62e0c8bef04ff4b48b4748b020be76725d5d",
"DeviceType": "Apple" | "Android", // Currently only present for "Apple" and "Android" devices
"Battery": {
"DataSource": "imobiledevice",
"TrustLevel": "paired",
"PairingSupported": true,
"HealthPercent": 95,
"CurrentLevel": 100,
"CurrentTime": 1613056296,
"StartingLevel": 100,
"StartingTime": 1613056293,
"CapacityNew": 1751,
"Capacity": 1678,
"ChargingStatus": "full"
},
"USBTree": {
"LocationID": 591470592,
"USBVersion": 2.0,
"USBPower": {
"State": "D0",
"Description": "On"
},
"USBSpeed": {
"Speed": "480Mbps", // Currently any of "1.5Mbps", "12Mbps", "480Mbps", "5Gbps", "10Gbps", "20Gbps", "40Gbps"
"Description": "High" // Any of "Low", "Full", "High",
// "SuperSpeed USB 5Gbps", "SuperSpeed USB 10Gbps", "SuperSpeed USB 20Gbps",
// "SuperSpeed USB 40Gbps", "USB4® 10Gbps", "USB4® 20Gbps", "USB4® 40Gbps"
},
"Endpoints": {
"Active": 6,
"Maximum": 8,
"Memory": 32768 // Amount of memory used (in bytes) for this node on the USB tree
},
"USBConnectionError": "string", // Only present on Windows if a device error occurs
// "DeviceFailedEnumeration" | "DeviceGeneralFailure" |
// "DeviceCausedOvercurrent" | // "DeviceNotEnoughPower" |
// "DeviceNotEnoughBandwidth" | "DeviceHubNestedTooDeeply" |
// "DeviceInLegacyHub" | "DeviceEnumerating" | "DeviceReset",
"USBErrors": [ // Only present if any errors are detected
// Errors can be any of the following:
"No open pipes : USB stack has not loaded the device",
"Invalid Device Descriptor : bLength was <N> instead of 18",
"Invalid Device Descriptor : Low speed devices require bMaxPacketSize0 = 8 (<N> was given)",
"Invalid Device Descriptor : Full Speed devices require bMaxPacketSize0 = 8, 16, 32, or 64 (<N> was given)",
"Invalid Device Descriptor : High Speed devices require bMaxPacketSize0 = 64 (<N> was given)",
"Invalid Device Descriptor : SuperSpeed devices require bMaxPacketSize0 = 9 (512) (<N> was given)",
"Invalid Device Descriptor : SuperSpeed device reporting less than USB 3.0",
"Invalid Device Qualifier Descriptor : bLength was <N> instead of 10",
"Invalid Other Speed Configuration Descriptor : bLength was <N> instead of 10",
"Invalid Configuration Descriptor : bLength was <N> instead of 9",
"Invalid Interface Descriptor : bLength was <N> instead of 9 or 11",
"Invalid Endpoint Descriptor : bLength was <N> instead of 7 or 8",
"Invalid HID Descriptor : bLength was <N> instead of >= 9",
"Invalid OTG Descriptor : bLength was <N> instead of 3",
"Invalid InterfaceAssociation Descriptor : bLength was <N> instead of 8",
"Invalid BOS SuperSpeedUSB Descriptor : bLength was <N> instead of 10",
"Invalid BOS SuperSpeedPlusUSB Descriptor : bLength was <N> instead of >= 16",
"Invalid BOS Billboard Descriptor : bLength was <N> instead of >= 48",
"Invalid BOS ContainerID Descriptor : bLength was <N> instead of 20",
"Invalid BOS FirmwareStatus Descriptor : bLength was <N> instead of 8",
"Invalid BOS PDConsumerPort Descriptor : bLength was <N> instead of 24",
"Invalid BOS Platform Descriptor : bLength was <N> instead of >= 21",
"Invalid BOS PowerDelivery Descriptor : bLength was <N> instead of 18",
"Invalid BOS USB20Extension Descriptor : bLength was <N> instead of 7"
]
}
},
"Port.2": {
"Port": 2,
"Current_mA": 0,
"Flags": "R D S",
"LocationID": 591597568
},
"Port.3": ...
}
Is global profile n enabled?
Example return value:
false
Fan speed.
Example return value:
100
A flag indicating if the system has been rebooted since power up. true – system has been rebooted or false – no reboot has occurred.
Example return value:
true
Is security armed?
Example return value:
false
The system identification text.
Example return value:
"cambrionix U8S-EXT 8 Port USB Charge+Sync"
Present PCB temperature in degrees Celsius. Measured temperatures ≤ 0 °C will return 0. Measured temperatures ≥100 °C will return 100.
Example return value:
37.7
Temperature error flags:
Example return value:
""
Upper limit of the acceptable temperature range that will trigger the error flag.
Example return value:
65.0
Highest PCB temperature in degrees Celsius. Measured temperatures ≤ 0 °C will return 0. Measured temperatures ≥ 100 °C will return 100.
Example return value:
39.9
Total current in mA for all USB ports.
Example return value:
0
Total power being consumed on all USB ports in Watts (W).
Example return value:
3.4
List of 12V supply rail error flags.
Example return value:
""
Upper limit of the 12V rail that will trigger the error flag.
Example return value:
14.5
Lower limit of the 12V rail that will trigger the error flag.
Example return value:
9.59
Current 12V supply voltage in Volts (V).
Example return value:
12.43
Highest 12V supply voltage seen.
Example return value:
12.52
Lowest 12V supply voltage seen in Volts (V).
Example return value:
12.31
Time in seconds the Cambrionix unit has been running since the last reset.
Example return value:
151304
Get USB Tree information. If a port is specified (sync only), then it will be the USB2 and USB3 (if applicable) trees associated to the specific port, otherwise it will be the entire tree.
Json object of USB tree.
Key | Feature set |
---|---|
Beep | 5V |
ClearErrorFlags | base |
ClearLCD | 5V |
ClearRebootFlag | base |
FiveVoltRail.OverVoltage | 5V |
FiveVoltRail.UnderVoltage | 5V |
InputRail.OverVoltage | PD |
InputRail.UnderVoltage | PD |
LCDText.ROW.COL | 5V |
Mode | base |
Port.N.gate | gate |
Port.N.led1 | base |
Port.N.led2 | base |
Port.N.led3 | base |
Port.N.leds | base |
Port.N.Mode | base |
Port.N.profiles | sync |
Port.N.RGB | gate |
Port.N.RebootDevice | sync |
ProfileEnable.n | 5V |
Reboot | base |
RebootDevices | sync |
RemoteControl | base |
RGBControl | gate |
SecurityArmed | 5V |
Temperature.OverTemperature | temperature |
TwelveVoltRail.OverVoltage | 12V |
TwelveVoltRail.UnderVoltage | 12V |
Set same mode to all USB Ports.
Sync mode can only be set on device that implement the
sync
feature set. Biased mode can only be set on devices
that implement the 5V
feature set.
mode:
With Python, this could be
# Example - setting all ports to sync mode
'Mode', 's') cbrx_connection_set(handle,
Or with JSON-RPC
{
"id": 0,
"jsonrpc": "2.0",
"method": "cbrx_connection_set",
"params": [
handle,
"Mode",
"s"
]
}
Set mode of a single USB port.
Sync mode can only be set on device that implement the
sync
feature set. Biased mode can only be set on devices
that implement the 5V
feature set.
mode:
With Python, this could be
# Example - setting port 1 to charge mode
'Port.1.mode', 'c') cbrx_connection_set(handle,
Or with JSON-RPC
{
"id": 0,
"jsonrpc": "2.0",
"method": "cbrx_connection_set",
"params": [
handle,
"Port.1.Mode",
"c"
]
}
Set the status of the first LED
0-255 with the LEDs flashing according to the bit pattern represented by the value.
With Python, this could be
# Example - setting port 1 LED 1 to flash rapidly
'Port.1.led1', 170) # 170 = 0b10101010 cbrx_connection_set(handle,
Or with JSON-RPC
{
"id": 0,
"jsonrpc": "2.0",
"method": "cbrx_connection_set",
"params": [
handle,
"Port.1.led1",
170
]
}
Set the status of the second LED
0-255 with the LEDs flashing according to the bit pattern represented by the value.
With Python, this could be
# Example - setting port 1 LED 2 to flash slowly
'Port.1.led2', 240) # 240 = 0b11110000 cbrx_connection_set(handle,
Or with JSON-RPC:
{
"id": 0,
"jsonrpc": "2.0",
"method": "cbrx_connection_set",
"params": [
handle,
"Port.1.led2",
240
]
}
Set the status of the third LED
0-255 with the LEDs flashing according to the bit pattern represented by the value.
# Example - setting port 1 LED 3 to stay on
'Port.1.led3', 255) # 255 = 0b11111111 cbrx_connection_set(handle,
Or with JSON-RPC:
{
"id": 0,
"jsonrpc": "2.0",
"method": "cbrx_connection_set",
"params": [
handle,
"Port.1.led3",
255
]
}
Set the status of all three LEDs
A 24 bit numeric value consisting of the individual LED settings as 8
bit values shifted and OR’ed together. i.e. led1 | (led2 << 8) |
(led3 << 16), so with led1 and led2 as zero, and led3 being
0b10101010 (decimal 170), the result should be 11,141,120 decimal.
On
a ThunderSync3, 255 is Green, 65,280 is red, 16,711,680 is Yellow. On a
ModIT, Blue is used instead of Yellow, but you can of course mix colours
into any RGB mix.
# Python example - setting port 1 LEDs to all flash at different rates
= 0b10101010
led1 = 0b11001100
led2 = 0b00111100
led3 = led1 << 16 | led2 << 8 | led3 # 11,193,404
pattern 'Port.1.led34', pattern) cbrx_connection_set(handle,
Or with JSON-RPC:
{
"id": 0,
"jsonrpc": "2.0",
"method": "cbrx_connection_set",
"params": [
handle,
"Port.1.leds",
11193404
]
}
Set RGBA colour of ModIT LEDs.
Colour argument can either be an integer (where you must supply full RGBA), or a string.
For a string, you can specify it as RGB, RGBA, RRGGBB or RRGGBBAA. Much like you can with an HTML colour. For example, use “FF0000” or “F00” for red, “FFFFFF” for white and so on. Optionally supply the alpha (intensity) digits, so “FFFFFF80” for half bright white.
Preceding ‘#’ is optional and will be ignored.
# Python example - setting port 1 ModIT LEDs to yellow
# This colour is the same as specifying "#FF0", "FF0" or "FFFF00FF"
'Port.1.RGB', "#FFFF00")
cbrx_connection_set(handle,
# or at half intensity
'Port.1.RGB', "#FFFF0080") cbrx_connection_set(handle,
Or with JSON-RPC, same colour but in short method:
{
"id": 0,
"jsonrpc": "2.0",
"method": "cbrx_connection_set",
"params": [
handle,
"Port.1.RGB",
"ff08"
]
}
Set the list of enabled profiles.
A comma separated list of profiles to enable e.g. 1,2,3
# Python example setting port available 1 profiles to 1, 2 and 3
"Port.1.profiles", "1,2,3") cbrx_connection_set(handle,
Or with JSON-RPC:
{
"id": 0,
"jsonrpc": "2.0",
"method": "cbrx_connection_set",
"params": [
handle,
"Port.1.profiles",
"1,2,3"
]
}
Reboot the device attached to the specified port.
Note that the device must be either an iOS or Android device. If an iOS device it must have been previously paired to the host computer. If an Android device, it must have USB debugging enabled and previously trusted the host computer.
Open or close specified gate.
‘open’, ‘close’ or ‘stop’ are valid options.
Returns true if successful.
The return is immediate if the command succeeds, but you should monitor the state of the required gate via cbrx_connection_get(handle, “Gates”) to ensure it completes.
# Python example to open gate of port 1
"Port.1.gate", "open") cbrx_connection_set(handle,
Or with JSON-RPC:
{
"id": 0,
"jsonrpc": "2.0",
"method": "cbrx_connection_set",
"params": [
handle,
"Port.1.gate",
"open"
]
}
Clear the LCD.
# Python example
"ClearLCD") cbrx_connection_set(handle,
Write the string on the LCD at (row, column). Row and column are zero based.
# Python example
"LCDText.0.0", "Hello World!") cbrx_connection_set(handle,
Enable / disable controlling of the unit controls. This will allow the LEDs or LCD to be updated or panel button pushes to be detected.
Allowed values: true | false | “auto”
# Python example
"RemoteControl", true) cbrx_connection_set(handle,
Enable / disable ModIT RGB LED control for ports. This does not require RemoteControl to be enabled.
Arguments:
boolean to enable or disable for all ports
or for a specific port, an object with options:
enable: boolean, port: number
or a range of ports, an object with options:
enable: boolean, start: number, end: number,
JSON example setting ports 1 to 8 to enabled:
{
"id": 0,
"jsonrpc": "2.0",
"method": "cbrx_connection_set",
"params": [
handle,
"RGBControl",
{
"start": 1,
"end": 8,
"enable": true
}
]
}
Enable / disable security feature. If the security is enabled, removal of a device from a port will sound an alarm and flash lights.
# Python example
"SecurityArmed", true) cbrx_connection_set(handle,
Beep for the number of milliseconds passed in.
Arguments: integer
# Python example - beep for 1/4 sec
"Beep", 250) cbrx_connection_set(handle,
Clear the reboot flag.
Arguments: true
# Python example
"ClearRebootFlag", true) cbrx_connection_set(handle,
Clear all error flags
Arguments: true
# Python example
"ClearErrorFlags", true) cbrx_connection_set(handle,
Reboot the hub now. The Hub API will attempt to re-establish connection automatically, but you should not expected to receive updated results for several seconds.
Arguments: true
# Python example
"Reboot", true) cbrx_connection_set(handle,
Reboot all of the devices attached to the hub.
Note that the devices must be either an iOS or Android devices. If iOS devices they must have been previously paired to the host computer. If Android devices, they must have USB debugging enabled and previously trusted the host computer.
Force the behaviour of a 5V over voltage condition.
Arguments: true
# Python example
"FiveVoltRail.OverVoltage", true) cbrx_connection_set(handle,
Force the behaviour of a 5V under voltage condition.
Arguments: true
# Python example
"FiveVoltRail.UnderVoltage", true) cbrx_connection_set(handle,
Force the behaviour of a 12V over voltage condition.
This is the same as TwelveVoltRail is the same as InputRail.
Arguments: true
# Python example
"TwelveVoltRail.OverVoltage", true) cbrx_connection_set(handle,
Force the behaviour of a 12V under voltage condition.
This is the same as TwelveVoltRail is the same as InputRail.
Arguments: true
# Python example
"TwelveVoltRail.UnderVoltage", true) cbrx_connection_set(handle,
Force the behaviour of an input rail over voltage condition.
Arguments: true
# Python example
"InputRail.OverVoltage", true) cbrx_connection_set(handle,
Force the behaviour of an input rail under voltage condition.
Arguments: true
# Python example
"InputRail.UnderVoltage", true) cbrx_connection_set(handle,
Force the behaviour of an over temperature condition.
Arguments: true
# Python example
"Temperature.OverTemperature", true) cbrx_connection_set(handle,
Enable or disable the global profile n
Arguments: boolean
# Python example, enabling profile 1
"ProfileEnable.1", true) cbrx_connection_set(handle,
When using the Python wrapper that provides the cbrxapi module, each time a call is made to the API, a socket is created. This socket is then used to send the command and receive the response before being closed.
If you are writing your own program, in whichever language you choose, you may wish to consider creating a single socket at the start of your communication with the Hub API and keeping this socket open until you wish to stop using the Hub API. Keeping the socket open for the lifetime of your communication with the Hub API will reduce the load on the system and lead to shorter communication cycles with the Hub API.
If you do choose to manage your own socket connections to the API, either as a long lived singleton, or else created on a per use basis, it is important that you do not close the socket before receiving the response from the final command. Closing the socket without waiting to receive the response may lead to the requested operation not being completed, this is especially important on set and close operations.
The Hub API will only accept connections from the local machine, unless a certificate has been provided. External connections must thereafter be secure types, such as https or wss.
Socket connections can be simple binary data, http GET requests or Web-sockets (such as from Node.js).
For example, pasting the following into the address bar of your browser should allow you to see quick results:
http://localhost:43424/?{"jsonrpc":"2.0","id":1,"method":"cbrx_discover","params":["all"]}
If there is no activity on an open handle for more than 120s, the
handle will be deleted. Subsequent calls attempting to use a deleted
handle will fail with CBRXAPI_ERRORCODE_INVALIDHANDLE
.
Software using the Hub API must be able to cope with this situation and
respond accordingly. Software may simply call cbrx_connection_open
again
in order to obtain a fresh handle.
The Hub API allows control of the LEDs that are present on some chargers or can be attached to other chargers. By default these LEDs are controlled automatically by the charger firmware to indicate the state that a port is in. In order for the LEDs to be controlled by the Hub API this automatic control must be disabled and this is done by setting the “RemoteControl” key to be ‘True’.
= cbrxapi.cbrx_connection_set(handle, "RemoteControl", True) result
If you wish to return control of the LEDs to the automatic control then you simply set “RemoteControl” to be ‘False’.
= cbrxapi.cbrx_connection_set(handle, "RemoteControl", False) result
Control of an LED is achieved by providing an 8 bit value which is interpreted in binary as a pattern that is continuously cycled through. So by setting the value 11110000b, the LED will flash slowly. The LED will be lit where there is a ‘1’ and unlit where there is a ‘0’. Alternatively setting the value 10101010b will make the LED flash fast. The pattern need not be symmetrical so 10010000b will produce two short flashes close together with a longer pause before the cycle repeats.
Any value set for an LED while RemoteControl is False will be overwritten and so have no effect.
A special argument of "auto"
in place of
True
allows the hub to override the user set LED pattern
when a device attached to that port is removed.
In some cases, battery information can be retrieved for connected
devices. For Android devices we can use adb
(from the
Android developer kit), and for iOS devices we use an in-built build of
libimobile. Additionally on Windows, if an iTunes
installation is detected, it can also be used. It should be noted that
this support could change with new versions of iTunes.
ADB can be used to query the battery level on any Android devices providing a few conditions are met.
See this page for details on enabling debug mode on Android devices. The only options that are required are to enable developer mode and USB debugging.
# Install Android platform tools on Linux
sudo apt install android-platform-tools
# Install Android platform tools on macOS
brew cask install android-platform-tools
# Install Android platform tools on Windows
# Goto https://developer.android.com/studio/releases/platform-tools
# Download SDK Platform-Tools for Windows
# Start the adb service with
adb start-server
The Hub API provides a means of controlling most of the features of Cambrionix Universal devices, however there are some limitations.
The Hub API does not currently support:
The related Recorder service which is an optional installation component can record events such as device health, charging history and connection events. These can subsequently be viewed in LiveViewer2. This is intended as a showcase of functionality that could be implemented. There is not currently any documentation for querying data because it is not yet finalised.
Code | Value | Description |
---|---|---|
CBRXAPI_ERRORCODE_IDNOTFOUND | -10001 | The unit ID passed in does not represent a Cambrionix unit or it has been disconnected since discovery was last run. |
CBRXAPI_ERRORCODE_KEYNOTFOUND | -10003 | A key that is passed in cannot be found. It may be misspelled or not exist in the dictionary for this unit. |
CBRXAPI_ERRORCODE_ERRORSETTINGVALUE | -10004 | The (key, value) pair was not acceptable. This could mean the tag does not exist or is misspelled, the value is of the wrong type or the value passed is invalid or out of range. |
CBRXAPI_ERRORCODE_INVALIDHANDLE | -10005 | The handle passed in to a function is not valid or no longer valid. This could happen either by passing in an incorrect value or if the handle has already been closed, or has expired due to 30 seconds of inactivity. |
CBRXAPI_ERRORCODE_TIMEOUT | -10006 | An operation towards a Cambrionix unit took too long to complete. It may have been disconnected or just slow to respond. It is worth retrying the operation. |
CBRXAPI_ERRORCODE_DROPPED | -10007 | The socket connection to a remote Cambrionix unit has been dropped.
To continue communication, a socket must be re-established by calling cbrx_connection_open
again. |
CBRXAPI_ERRORCODE_METHOD_REMOVED | -10008 | The method has been removed. |
CBRXAPI_ERRORCODE_AGAIN | -10009 | System not ready. Try again. This is likely caused by a very prompt call to an Hub API function and the system has not progressed through startup enough to service it. |
CBRXAPI_ERRORCODE_FIRMWARE_UPDATE | -10010 | Error performing firmware update. |
CBRXAPI_ERRORCODE_FIRMWARE_FILE | -10011 | Firmware file error. This would usually be due to file format errors. |
CBRXAPI_ERRORCODE_DEVICE_NOT_FOUND | -10012 | Device not found. |
CBRXAPI_ERRORCODE_HUB_NOT_FOUND | -10013 | Hub not found. |
CBRXAPI_ERRORCODE_CONNECTION_ERROR | -10014 | Could not open the serial port connection to the hub. |
CBRXAPI_ERRORCODE_INVALID_DYNAMIC_NAME | -10015 | Invalid Dynamic hub name. |
CBRXAPI_ERRORCODE_LOCKED | -10016 | Hub is locked via cbrx_connection_closeandlock . |
Version | Changes |
---|---|
3.22.0 | [macOS] Added support for macOS Intents and Siri Shortcuts. This allows you to create custom shortcuts that can be triggered by voice commands or by tapping on a button in the Shortcuts app. You can create shortcuts that trigger actions such as setting a port mode or changing LEDs. See the API reference for more information. |
3.21.1 | [macOS] Better deal with issues caused by macOS sending USB events in the wrong order. |
3.21.0 | Added a configuration page for some options. Access is via
http://localhost:43424/config. This can configure Debug Logging, Battery
Updates and the Certificate configuration. Fix Blacklist Keonn FTDI devices from being detected as a Cambrionix hub. Fix Ensure that cbrx_discover('local') does not return an entry for FTDI
devices that are not Cambrionix hubs.[Windows] Fix rare case where USB tree scan can get stuck querying a host controller that is in a bad state. [Windows] Fix missing DevicePath property for USB devices that are not hubs. |
3.20.3 | [Windows] Fix cases on some Windows machines where USB3 devices would not appear on SuperSync15 hubs. This was related to power management settings on the USB3 controller. |
3.20.2 | Fix error showing marketing-name missing during battery update on newer iOS devices. |
3.20.1 | Fix issue where a SuperSync15’s virtual serial device was
incorrectly mapped to a non existent USB3 companion. [Linux] The above fix re-enables the Linux scanning for USB descriptors. We are hoping that further Linux kernel updates have addressed the problems with USB tree scans stalling when reading USB descriptors. If this is not the case, please let us know. I’m planning on an option for this to cover all cases. And an easy way to set such options. |
3.20.0 | Add cbrx_hub_get(serial, "EndpointMemory") to get the
total memory used by all endpoints on a hub, connected ports and so
forth. This includes both hub only and nested hub information.Add cbrx_get_usb("Endpoints") to provide a summary of all
endpoint usage across the system. This is broken down by host
controller. Thunderbolt devices, such as the ThunderSync3-16 have their
own host controllers, so there is additional information on these
entries to show which hub they belong to.Implemented start of new restful API based at http://localhost:43424/api/v1/. See http://localhost:43424/api/v1/swagger for information. More to come on that soon! Added /api/v1/hubs/{hubId}/endpoints to
achieve same result as
cbrx_hub_get(serial, "EndpointMemory") mentioned
above.Added /api/v1/endpoints to achieve the same
result as cbrx_get_usb("Endpoints") shown above.[macOS & Linux] Fix issue where volume mapping for flash drives and other removable media would not be detected, because the two operating systems can take a few seconds to mount the volume after the device is connected. Fix a crash on shutdown of service, such as when you install a new version. [Linux] Due to the up-coming release of Cambrionix Connect, we are removing the on-demand service option (and the associated –persistent command line option). This is because an on-demand service cannot keep Connect up-to-date with the latest information about hubs and devices. |
3.19.3 | Fix issue with not being able to apply nvram settings via
cbrx_connection_set(hubSerial, 'settings', ...) . |
3.19.2 | [macOS] Fix USBTree scan not completing on MacMini M1. |
3.19.1 | Fix crash caused by posting Unidock state to Cambrionix Connect. |
3.19.0 | Add extra information for iOS devices where phone details are
included. This includes 'PhoneECID' ,
'PhoneProductType' (ie: iPad4,4),
'PhoneOSType' (ie: iPhone OS), 'PhoneColour'
(ie: ‘#e1e4e3’), 'PhoneDiskUsage' (this is a map of various
values).Fix service GUID being lost when upgrading from 3.17 to 3.18. Fix some recorder output (http headers etc) claiming to be the Hub API. [macOS] Fix possibility that devices can linger in the USBTree if they’re removed about 250ms after another device. [macOS] Fix issue where socket replies larger than 1Kb would sometimes not all be sent. Fix issue where a request for 'FirmwareRequirements' would return an error if the hub has
no firmware, but is instead in the bootloader.[Windows] Fix issue where you get a warning that the recorder is still running when you upgrade the API. [Windows] When the Recorder Service is not selected, it will still be installed as always, but will now be added to Windows Services as a Manual start. This allows you to start it easily from the Services control panel if you need it. |
3.18.0 | Internal refactoring to improve performance and reliability of the API and to allow for future improvements and code sharing between other services. We’ve noted a 2 fold improvement in the API’s responsiveness to requests under heavy load. |
3.17.0 | Implement post of Hubs and Devices to Connect service to provide a
faster way for Connect to get the latest information about hubs and
devices. [macOS and Linux] Ensure that serial ports to hubs are not opened if they are already opened by another process. It turns out this is a valid thing to do for these operating systems, but may have been responsible for various issues in the past (corrupt serial data, bad firmware updates), since the Hub API could also open the same serial connection to a hub that was already opened elsewhere. This is not an issue on Windows where all serial connections are exclusive by design. |
3.16.0 | Add TotalInTree.Endpoints and
TotalInTree.Memory to device Endpoint
information in cbrx_discover('all') and
cbrx_get_usb('tree') . This totals all the endpoints in the
USB tree for a given hub. Note that this will include endpoints and
memory on chained hubs if there are any.Fix rare crash when timeout after long USB scan occurs. Fix issue where recently re-attached hub could show no devices due to a race condition. Also manifested as not showing its own location ID. Fix bug in libusbmuxd getting stuck in a loop and never completing, resulting in battery information not being available. Fix HostSerial property not always being
present in cbrx_find results. |
3.15.2 | For a single http socket connection, fix issue that subsequent requests do not respond. |
3.15.1 | Fix authentication issue for local API connections from Connect. |
3.15.0 | [macOS and Linux] Increase the number of file handles possible for
the API. This should ease problems for client processes that create more
than 256 socket connections to the API in a short period of
time. [Windows] Fix a bug that could return an error code from cbrx_apidetails, instead of the version details. [Recorder] Fix a bug that would cause the Recorder to fail to handle this error code correctly which caused the Recorder to stop responding to requests. [Recorder] Fix issue that prevented Connect from being able to fetch graph data from remote Recorder API instances. [Recorder] Fix response of /api/v1/hubs/{serial}/events endpoint. [Windows] Updated installer to not select installation of Python by default. |
3.14.0 | Added Swagger documentation for both the API and the Recorder
services. This serves as documentation for the updated recorder query
API as well as a few endpoints that are available to the API itself.
API: http://localhost:43424/swagger Recorder: http://localhost:43426/swagger Fix issue with Task Lists getting stuck in a state where they would not complete. This had a knock-on effect of stalling other operations in the API. [Windows] Fix an issue which could cause the Windows installer to fail to terminate the recorder service during an update, leading to a reboot being required, or the necessity to manually stop the service before updating. [Windows] Fixed the API’s cbrx_exit, and the recorder’s /exit endpoint not working on Windows, which caused Connect’s Restart API button to simply do nothing with no
feedback.[Linux] Fix issue with the API stalling after a USBTree scan. The cause of this is unknown at this time, so this fix is just to disable scanning for each device’s BOS descriptor, which can hang for unknown reasons. |
3.13.0 | [Recorder] Update all recorder queries that return more than one
result to accept pagination parameters for the query to allow for more
efficient retrieval of large amounts of data. Add offset
and limit parameters to the query. This will change the
results from a simple array of all events to an object with a
_metadata field and an result field. The
_metadata field will contain the total number
of results and the offset , limit parameters
used for the query and links for the next and
prev query. The result field will contain the
array of results. The offset parameter is optional and
defaults to 0. The limit parameter is optional and defaults
to all. The limit parameter can be omitted to return all
results from the offset onwards.[Recorder] The start and end data limits are now optional and
will default to the start and end of the available data if not
specified.[Recorder] Added a new recorder API to supersede the old style. Please see the http://localhost:43426/api/v1/help link for details. When the new interface is used (for queries that return more than one result), the results will always contain the _metadata field. |
3.12.5 | [Linux] Fix fetch of SSL web content used for Connect verification. |
3.12.4 | Fix authorisation from Connect in recorder service. |
3.12.3 | [Windows] Fix issue during update installation where the recorder service would not exit properly, causing the update to require a reboot to complete. Note that this will not fix the issue for the existing installation, but will prevent it from happening again going forward. |
3.12.2 | Fix exception in extended logging when cbrx_hub_set is used. |
3.12.1 | Update authorization for the Connect service. |
3.12.0 | Added “HardwareInformation” to get dictionary to fetch both hub
information and port specific information to individual ports on the
hub. This information is static and related to the known configuration
of each Cambrionix hub. This includes information such as the official
web site, dimensions, tolerances and so on. Added a simple Rust example for querying the API. Added Endpoints.MemoryLimit field to USBTree information if the
limit is known for a host controller. Currently this is limited to the
FL1100 controller which has 1Mb of endpoint memory found in newer M1
macs and Cambrionix ThunderSync hubs.Fix missing endpoint usage information on Thunderbolt root controllers, such as on a certain M1 macOS machines. Make sure we strip custom commands of whitespace before sending them from cbrx_connection_cli. Fix cbrx_connection_set(“Settings”, …) from not returning the results, but just ‘true’. Update the firmware updater code to align with command-line-updater 2.2.1 to support bulk firmware files. [macOS M1] Fix issue that would cause ports to reset for iPhones on latest macOS. |
3.11.1 | Fix crash with cbrx_connection_set in some cases. |
3.11.0 | Allow cbrx_connection_get and
cbrx_connection_set to accept a hub’s serial number instead
of only a previously opened handle. This is for convenience (and behaves
the same as cbrx_hub_get and cbrx_hub_set ),
and it should be noted that for multiple requests, it may still be more
time efficient to use handles. Handles will ensure that a hub remains
active for at least 30 seconds, whereas no such guarantee exists when
using the serial number directly.Add a “DevicePath” field to USBTree information which gives the platform specific path for the device. This path is now also included in searches originating from the cbrx_find command.When collecting battery information, give indication in the port’s results if ADB is not running, and for Windows if the Apple Mobile Device Service is not running. Add a ‘RootLocationIDs’ field to cbrx_discover(‘all’) information to provide an array of all of the root USB entry points for a hub. [Linux] Persist the –persistent installation option if the API is updated. This also required a slight amendment to the --persistent option
so that once –persistent is enabled, it will now require
--persistent off to disable it.[Linux (mainly)] Improve responsiveness of API when it initially launches by not requiring that the initial discovery has fully completed before replying to basic requests that don’t require such discovery to complete. Fix issue that could cause firmware update to fail to start. Fix issue that could cause the battery update to stop triggering. Fix the result of RootLocationID in cbrx_discover(‘all’) results to be the actual root location ID for hubs such as the PowerPad15 or SuperSync15. [Windows] Fix some cases where a USB Flash Drive’s drive letter was not detected if there was a case mismatch between the device ID and the USB serial number. Changed to match by the unique device ID instead of serial number. [macOS] No longer requires Rosetta to be installed to install CAPI on ARM architecture. |
3.10.0 | Implemented more thorough discovery of attached USB drives to
include devices such as USB SCSI drives and their mount points. This
also adds a "Volumes" field to the existing
"FlashDrive" information to list all volumes on the USB
device. We have not removed the existing information (that was
restricted to a single mount point) to remain backwards
compatibility.Fix rare crash that could cause timers to stop working. [macOS] Fix recorder service install failing to create a valid plist file. [Linux] Fix issue that could cause duplicate entries in the USBTree when Thunderbolt hubs are present and have a non-Thunderbolt child hub. [macOS] Fix issue with not showing hubs with older Mac hardware (circa 2017). |
3.9.2 | Fix issues with dynamic hubs not responding correctly if very recently opened. |
3.9.1 | Fix issue where USB notification events could occur in the wrong order, leading to confusing in both the API and external event listeners. |
3.9.0 | Teach API how to update firmware for latest hardware. [macOS] Fix issue where two devices being removing between 250ms and 1sec of each other could cause one of the devices to appear to still be present. Fix issue of setting port modes and other settings that could appear to fail. Ensure when LiveViewer runs the bundled API that those bundled instances check whether the API proper is already running and just exit if it is. When started as a service, ensure that any LiveViewer bundled instances of the API/Recorder are asked to exit immediately. Fix some crashes caused when exiting the API or Recorder services. Fix issue with API becoming unresponsive to a hub until all opened handles are closed and opened again. [Linux] Fix crash or infinite loop after a USBTree update. |
3.8.1 | [macOS] Fix issue of API getting confused about hubs when they are moved between different ports. |
3.8.0 | Remove requirement of running ADB executable to query Android
battery information and instead make direct connection to the running
ADB server. This fixes issues such as the API service not having access
to the folder where the ADB executable is in. Fix rare crash with timers that are removed while they’re already running. Address long wait times for cbrx_discover(‘all’) when there are several hubs, especially if one of those is unresponsive. Fix crash or hang when a USB device has invalid descriptor information. Fix data returned from recorder to LiveViewer when the requested step size is exactly 30 seconds which caused gaps in the graphs due to time slippage where recorded data is always just a little over 30 seconds. Fix recorder from failing to ever restart if there was an issue, such as failing to connect to the API. [Linux/macOS] Fix issue of getting stuck in a loop of crashing. [macOS] Fix issue of the API not starting (affected 3.7.0). Fix cbrx_connection_set errors, such as changing port mode. The action was always taken, but reported as a failure. |
3.7.0 | [Linux] Add a new –persistent option (to be used alongside –install)
to make the service run all the time instead of being an on-demand
service. This can help with responsiveness of API requests when the USB
scan takes too long in on-demand scenarios. Add a few missing dictionary items that are in API reference but not in API. Port.N.USBStrings Port.N.Voltage_10mV TotalPower_W TemperatureMax_C Fix definition for USB descriptor for OTG devices. Fix cbrx_connection_cli and a few other internals from interfering with each other when they run. Fix issue with aligning USB3 and USB2 trees when their depth is not equal. [Linux] Fix deb package not having dependency to libudev1. |
3.6.0 | Added HostPortLocationID field to cbrx_discover(‘all’). This is the
USB node that handles the serial communications to the hub. For USB3 hubs, added USB3CompanionLocationID field to cbrx_discover(‘all’). This can be used to identify the USB3 part of the tree from cbrx_get_usb(‘tree’). Implemented more reliable and platform independent detection of USB3 to USB2 companion mapping. Fix rare crash that could occur when a socket connection was being closed and there was still pending data in the out buffer. [macOS] Fix issues when crash handler not restarting the service. Give more meaningful feedback if ADB path cannot be determined, such as if the server is started from within a user’s folder, which the service may not have access to. [Windows] Fix issue that caused a build system behaviour change to mean the API now required MSVC runtime libraries. |
3.5.0 | Removed the self-signed certificate. There is now a cbrx_certificate
command to supply your own certificate and private key for the API to
use. See the API reference for details. Both the API and the Recorder
will use the same certificate once defined. Existing socket connections
are left alone if the certificate changes. New SSL connections will use
the updated certificate. The listen socket will only listen on 0.0.0.0
if there is a defined certificate, otherwise will fall back to localhost
only connections. This is updated automatically if the certificate
configuration changes. Add cbrx_get_usb(‘descriptors’, “serial_number” / locationID) method to retrieve all information regarding a USB device that is available. This is essentially an entire dump of information relating to Chapter 9 of the USB 3.2 specification for the specified device. Devices can be queried either by their serial number, or by their location ID. With an optional 3rd argument to retrieve the raw bytes from descriptors in either ‘hex’ or ‘base64’ strings. You can also get the USB tree now via cbrx_get_usb(‘tree’). We already had the cbrx_get_usbtree method, but felt this change was good for future proofing. The old method will continue to work indefinitely. Fix issues where some expected result errors from cbrx_connection_set were not fed back to the JSON response correctly, resulting in misleading errors. [Windows] Re-factored USB tree scan to simplify things internally and allow capture of lower level properties. This means we can now capture Windows problem codes (The ones you see in Device Manager when a device cannot start). These are made available in “USBErrors” output in cbrx_get_usb(‘tree’) and individually for USB devices in PortInfo. You can look forward to seeing this information in a future version of LiveViewer. [macOS] Fix issue not finding hubs when using the USBLimitFix that forces USB to use EHCI instead of XHCI. [Linux armhf] Fix USB tree scan causing stack corruption. Fix incoming IPv6 addresses not being recognised as loopback addresses if they’re mapped from IPv4 addresses. Fix responsiveness in API when hundreds of requests are made in quick succession. Fix issue that caused USB events to be missed while a USB tree scan was already underway, which could lead to devices not appearing in LiveViewer or from relevant API queries. |
3.4.3 | [macOS] Fix USB nodes not being found when connected to the standard USB ports on the back of a MacMini9. |
3.4.2 | Fix lack of rebooting and rebooted notification after a hub completes firmware update. |
3.4.1 | [Windows] Fix crash in USB scan under certain hardware conditions. |
3.4.0 | Capture USB errors and make them available to PortsInfo and the
like. These can be errors related to invalid configuration descriptors
that can help to identify issues with USB devices. See PortsInfo in API
reference for possible errors. Properly detect Android and Apple devices based on their Interface descriptors to optimise battery info collection. Also provide the new "DeviceType" field in
PortsInfo that can be "Apple" or
"Android" .[macOS] Read USB version from USB device descriptor’s bcdUSB field rather than guessing it based on reported speed. Fix cbrx_connection_get(“Settings”) from showing stale settings if they were updated between calls, or externally from the API. |
3.3.2 | [Windows] Fix detection of individual Thunderbolt root controllers. |
3.3.1 | Fix issue where a hub could be forgotten, or report incorrect
devices attached if it moves around on the USBTree. This was often the
case when dealing with Thunderbolt hubs on Windows as this would usually
cause the entire tree to change. Fix rare crash if a request for USB tree data was received while a device was being removed. |
3.3.0 | PortsInfo, PortInfo.N and get_usb_tree now include USB endpoint
usage information. These are represented as
Endpoints: {"Active", N, "Maximum": N} . Active are for the
current USB configuration that the device is using. Maximum are for the
largest configuration that the device can choose to use.They also now include the device power state if not D0 (fully
powered). These are represented by the fields USBPowerState
and USBPowerStateMeaning . These can respectively be
D1 Off , D2
Low power , D3 Deep sleep .The same API queries will now also provide USB connection speed information, as well as connection speed capability when its a USB3 device. This information can indicate that you are using the wrong cable, if for example, the USBSpeed.Speed field says ‘480Mbps’, but the USBSpeed.Capability.Speed field says ‘5Gbps’, which could indicate that a USB3.1 device is connected via a USB2 cable. USBSpeed.Speed will indicate one of: 1.5Mbps , 12Mbps ,
480Mbps , 5Gbps , 10Gbps or
20Gbps . There is also a USBSpeed.Description
which will describe this speed as one of Low ,
Full , High , SuperSpeed ,
SuperSpeedPlus or SuperSpeedPlusBy2 .The USBTree query (cbrx_get_usbtree) will now contain extra elements in the root indicating the host controllers that the child hubs and devices are connected to. This includes a new field "EndpointMemoryUsed" and
"EndpointPeakMemoryUsed" which will indicate in bytes how
much of the host controller memory has been consumed by endpoint usage
on the host controller hardware, and the maximum usage seen so far.
Typically, the available memory on an older Intel chipset controller is
512Kib. Other controllers, such as ASMedia xHCI controllers and newer
Intel controllers will have more available endpoint memory.Add USBConnectionError to USB nodes and PortsInfo information that are not considered connected which may help to determine USB errors. This can be any of: DeviceFailedEnumeration, DeviceGeneralFailure, DeviceCausedOvercurrent, DeviceNotEnoughPower, DeviceNotEnoughBandwidth, DeviceHubNestedTooDeeply, DeviceInLegacyHub, DeviceEnumerating, DeviceReset. Remove duplicated USBTree information in PortInfo.N and PortsInfo . This will largely
now be restricted to endpoint information and the new USB information
described above, except for child items if there is a hub
connected.[macOS] Fix issue where ports on ThunderSync U16 were not mapped correctly. [macOS M1] Due to changes to the internal USB architecture for M1 macOS, the USB scan has been re-written for macOS to allow non-Thunderbolt USB devices to be detected correctly. Added Port.all.LocationID to retrieve information about all ports
and their possible location IDs. Without additional arguments, this
returns an object keyed by port number with "USB2" ,
"USB3" and "Current" entries.
"USB3" will only be present for a USB3 hub. Current
represents the current location ID of the device connected. This can
vary between the USB2 or USB3 entries depending on the device type. If
specified with an extra "USB2" or "USB3"
argument, then the return value will be a single level object keyed by
port number and contain only the location IDs for that USB
version.Port errors for Universal chargers (PowerPad, SuperSync, ThunderSync3-16 etc) will now be detailed in "PortErrorFlags" field of PortInfo.[macOS] Fix issue where example scripts were put in wrong folder during install, and so would never configure correctly. [Windows] Simplify installation and removes FTDI driver install as these drivers are installed automatically by Windows. [macOS] Added automatic workaround for Apple devices that fail to appear in Apple Configurator and other similar tools. This should mean Apple devices will appear promptly in all cases whilst the API is running. Note that this was not a fix for anything, but rather a nudge to the OS that it may have overlooked a device. Fix for not being able to clear notifications mask by supplying empty array. |
3.2.9 | [Linux] Fix crash in avahi cleanup. |
3.2.8 | Fix crash in 'Health' response if a firmware update has
just been triggered. |
3.2.7 | Re-implement cbrx_connection_closeandlock and cbrx_connection_unlock. |
3.2.6 | [Windows] Implement a more robust fix for chained ThunderSyncs that replicate the same devices from the first in the chain to the rest down the line. |
3.2.5 | Publish telnet status interface on localhost instead of publicly. |
3.2.4 | Stop reporting battery level as 0 when a device has not yet been paired. |
3.2.3 | Fix occasional crash during discovery. |
3.2.2 | [Windows] Fix issue where chained ThunderSyncs would replicate the same devices from the first in the chain to the rest down the line. |
3.2.1 | Ensure that current port states are refreshed before responding to a
cbrx_discover(‘all’) when the API had currently been idle. This ensures
that devices are correctly populated, instead of populating with the
previously cached state. Cope better with corrupted data from a hub’s CLI. Fix a few missing dictionary values. |
3.2.0 | Added support for SSL based https and wss (Secure WebSocket)
connections. This is a work in progress and currently uses a self-signed
certificate, however the content is still encrypted. Most likely, we’ll
provide a method for customers to supply their own CA signed certificate
and private key for the API to use for SSL connections. Add RebootDevices and Port.N.RebootDevice to set dictionary to reboot all/specified trusted Android or paired iOS devices. |
3.1.5 | [Windows] Fix installer that could leave very old examples around in wrong folders that could confuse LiveViewer. |
3.1.4 | [macOS] Fix resource leak issue in USB tree scanning which could cause the service to stop functioning correctly after several days of use. |
3.1.3 | [Linux] Fix issue with updating CambrionixRecorderService binary while it is running. |
3.1.2 | Improvements to python async example |
3.1.1 | Fix bogus notification that a hub has become unresponsive when a hub
connection handle times out due to inactivity. [Linux] Fix service configuration to prevent parse errors from systemd. |
3.1.0 | Now discovers USB flash drive mounting points and makes this information available in PortsInfo, cbrx_discover(‘all’) and a port’s ‘FlashDrive’ get function. Note that this is currently limited to the first partition found on a flash drive. |
3.0.2 | [Linux] Fix issue where a USB tree discovery never completes,
causing the API to be left in a bad state never to update it
again. [macOS] Fix issue where a serial connection could get frozen while shutting down, eventually causing the service to run out of file handles. [macOS] Deal with odd macOS issue that could cause large portions of data from the hub’s CLI to be lost which caused the API to get confused and unable to parse the hub’s state. |
3.0.1 | [Linux] Fix issue when service is triggered by systemd and cbrx_discover is run before the actual discovered results are ready. |
3.0.0 | Significant re-write of internal system responsible for discovery of
hubs and usage of serial port to increase reliability and
responsiveness. Serial connections to Cambrionix hubs are now closed within a few seconds when not in use after a cbrx_connection_close command, or after 30 seconds due to
timeout. This allows immediate usage of a hub’s serial interface (such
as via PuTTY) when it is not directly in use.Improvements to API reliability after a hub’s firmware has been updated and the hub is rebooted. Fixed issues with updating firmware on chained hubs (such as with Unidock). Parent hub’s are not rebooted until child hubs have completed their own update. USB Tree scanning occurs four times faster, leading to improvements to the responsiveness of USB devices being added or removed and appearing or disappearing via USB information, such as to LiveViewer. [Linux] Fix issues with running the CambrionixRecorderService under Linux. This can now be successfully enabled after installing on Linux by running: sudo /usr/bin/CambrionixRecorderService --install .[Linux] Fix issue that cause Cambrionix services to log everything to syslog rather than only errors and warnings. In the event of a crash, the services no longer re-generate duplicate crash logs for the same crash, but instead increment a counter in an associated file with the crash. It will also clean up old crash logs from previous versions since they likely out of date. **[BREAKING CHANGE]* Behaviour changed for Battery query of Android devices. It is now required to have the ADB server running independently in order to fetch Android battery information. This was necessary because it is quite normal for the ADB process to be logged in as a specific user with the authority to query the device. Therefore, the API will no longer attempt to query Android battery information if the ADB process is not already running, and nor will it attempt to start the service itself, as this can cause issues with ADB inheriting handles from the API and causing its own issues. You can start the adb server by running the following command in a terminal, or during your normal system startup: adb start-server |
2.21.18 | Fix issue where updated jsonrpc_websocket library Python 3.4+ broke the new Python asyncio examples. |
2.21.17 | Ensure hub discovery is not run multiple times simultaneously. |
2.21.16 | Fix battery update from stalling when it thought there was no API connections. |
2.21.15 | For USB devices that draw zero power, still allow them to show as an attached device if they are present on the USB tree. Note that this is in conflict to what the hub will report (i.e. port is not attached) via it’s ‘state’ command because the hub considers a device that draws no power to be detached. |
2.21.14 | Fix occasions during battery update could cause the API to appear to drop connection to the hub or time out. |
2.21.13 | Fix issue where Linux could skip discovering new USB devices. |
2.21.12 | Add support for Cambrionix TS3-C10 Type-C Desktop Charger. |
2.21.11 | Ensure cbrx_connection_set errors ‘Error setting value’ include meaningful error information from the hub if applicable. |
2.21.10 | Fix issue that could cause battery update loop to run excessively when there are no devices with battery information. |
2.21.9 | [macOS] Fix issue which can cause firmware update to not function on macOS 11.14. This appeared to be a bug in macOS itself as we found a lot of chatter about the same thing. |
2.21.8 | Fix issue where a hub may not be discovered if it has a newer version of FTDI chip. |
2.21.7 | Fix issue with excessive CPU usage when a lot of ‘set’ commands are issued at the same time. |
2.21.6 | Update gate state parser to deal with ModIT MCB firmware 0.10. |
2.21.5 | Fix issue when cbrx_connection_cli was used with a command that was also dealt with internally to maintain hub states. |
2.21.4 | [Windows] Fix USB tree scanning when using the Fresco Logic Thunderbolt drivers, as apposed to the Windows supplied ones. |
2.21.3 | Internal fix to support LiveViewer Test suite. |
2.21.2 | [macOS] Fix issue with dependent libraries that targeted most recent version of macOS and so would not run on an older system. |
2.21.1 | [Linux] Fix issue where API could get into unresponsive state after initial connection. |
2.21.0 | Added new asynchronous Python example that uses the Python 3.4
asyncio functionality. This is now the preferred method of using Python
with the API, and all older Python 2. examples have been deprecated and moved to a sub- folder. Made the old Python examples more tolerant (work) with being run with different Python versions. Added new C# example for Windows and macOS. Added new VB.NET example for Windows. |
2.20.6 | Fix issue where recorder can truncate the response data if it is too large. |
2.20.5 | Fix issue with recorder service using CPU when idle. Fix issue with recorder that meant it would often not record hub and device states. |
2.20.4 | [Linux] Account for oddity in Linux where the service triggered socket does not work, so the service exits for re-triggering. |
2.20.3 | [Linux] Fix issue where the service could fail to exit because the startup had not fully completed. |
2.20.2 | [Linux] Fix crash issue when a connection is made as the service is exiting. |
2.20.1 | Fix issue which could cause 1 thread to spin using CPU. [Linux] Fix issue with service not quitting in the normal manner after receiving API requests via HTTP GET. |
2.20.0 | Add configuration options for battery updates. These can be set with cbrx_config_set or via LiveViewer 2.17.0 onwards. Also lowered the default update frequency from 20 to 60 seconds, and set the default concurrency to 2. |
2.19.2 | [Windows] Fix issues when moving a ThunderSync hub between host ports which would cause the hub’s ports to subsequently be assigned the wrong numbers. |
2.19.1 | Fix cbrx_discover(“all”) returning no devices when there’s no recent cbrx_connection to that hub. |
2.19.0 | Support for LiveViewer notifications indicating when hub’s are not connectible because their serial port is already open by another application. |
2.18.3 | [Linux] Fix service issues. |
2.18.2 | Fixed an issue introduced in 2.16.5 where discovery hash would not
be stored, causing multiple discoveries of hubs and notifications
therein. Correct issue with logging locations and empty log files introduced in 2.18.0. |
2.18.1 | Fixed an issue where cbrx_connection_get for ports could return empty results when devices are present. |
2.18.0 | Support running in bundled mode from within LiveViewer. This allows
you to run LiveViewer without installing the API. If you need scripting
support when LiveViewer is not running, then you should still install
the whole API, which you can now do from the LiveViewer settings. Fix crash in logging if recorder is running. |
2.17.1 | Fix issues with standard USB hubs and devices not being visible to the API on Apple M1. |
2.17.0 | [macOS] Support for Native Apple Silicon. All API binaries are now Universal x86_64 and arm64. |
2.16.7 | Fix issue on Apple M1 where Thunderbolt hubs would not show
information about connected devices. Fix issue detecting a SuperSync15 device on macOS when the LocationID of the hub starts with a 0. |
2.16.6 | Fix issue of starting ADB twice simultaneously which lead to Android battery reading issues. |
2.16.5 | Fix crash in firmware updater. Fix issues with detecting SuperSync on macOS and Windows when it has no firmware. Fix 10 second connection delay when a hub has no firmware. |
2.16.4 | Fix crash in timers that could cause the API to stop detecting new devices. |
2.16.3 | [Windows] Ensure all installations of Python are configured during installation to cure problems where a different version of Python in the path was not configured and fails to run test script. |
2.16.2 | Fix issues with base64 library on very old processors. |
2.16.1 | Fix extended battery information for iPhone8 and later. Always returns error information on battery data collection, even with paired iPhones which may still refuse certain information if locked. |
2.16.0 | Add logging configuration support. |
2.15.5 | Fix issue with API not responding on macOS after a reboot. |
2.15.4 | [Linux & macOS] Fix issue with serial communications to hub that could cause it to stop updating correctly. |
2.15.3 | Fix some Port.N.* dictionary items lingering long after
a device is removed. |
2.15.2 | Fix parsing issue on PDSync with older firmware. |
2.15.1 | [Linux] Fix issue with detecting removed USB devices after the first
device was removed. [Linux ARM] Fix WebSocket handling which corrupted the return data. |
2.15.0 | Fix issues with EnabledProfiles, Port.N.Profiles and
Profile.N.enabled. Change version numbering from N.N.BUILD to standard semver.org method of N.N.N+BUILD or N.N.N-beta+BUILD and so on. |
2.14 | Fix RFID reader functionality broken in 2.13. |
2.13 | Fix issues with Thunderbolt showing wrong port mappings when
unplugged and reconnected. Fix issues with some cbrx_connection_set combinations not working after a hub is unplugged and reconnected. Fix issue with EtherSync discovery stalling in calls to Bonjour API causing further discoveries to also stall. Fix issues with Android battery information collection stalling because adb hangs. Improve RFID reader so that removal of RFID tag can be detected as well as arrival. |
2.12 | Add Battery Health for iOS devices. This should provide the same
result as the Battery Health page in iOS introduced with 12.3. Add IMEI and WiFi Mac Address to device’s details in port results. |
2.11 | Add Linux ARMv7 support - Tested on oDroid XU4 with Ubuntu 18.04 LTS. |
2.10 | Fix issue where hubs could disappear from the API after a
reboot. Fix issue where Linux could misread the USB location of a hub. |
2.9 | To ensure we don’t get further issues fixed by 2.6, we’re implementing a fail-safe that will automatically launch extra worker threads if jobs are not serviced within 200ms by adding Watchdog to internal task manager to ensure jobs are always serviced in good time. |
2.8 | Fix issue during startup where USB tree scan would end up waiting for a lock for discovered iOS devices that were currently being provisioned. |
2.7 | Fix issue where an exception in IOContext thread would cause the thread to exit and cause the API to stop responding. |
2.6 | Fix libimobile timeouts causing all task manager threads to be busy
and not service further jobs. Responsiveness of the initial opening of a hub greatly improved so that far less work is required internally before further commands can be issued. Battery information now included in cbrx_discover("all") data. |
2.5 | libimobile has been built into the API now for a more reliable method of collecting battery information for iOS devices. |
2.4 | Add cbrx_hub_get , cbrx_hub_set ,
cbrx_device_get and cbrx_device_set .Added "rfid-received" as a new notification type. |
2.3 | Add Node.JS example script. Fix NVRAM settings_set error. Fix generated HTML documentation styling. Add cbrx_connection_cli method. |
2.2 | Many stability and performance improvements. Add cbrx_notifications .Add cbrx_firmware .Add support for LiveViewer 2 which includes Websocket and HTTP GET capabilities. Add CambrionixRecorderService as optional installation service
to record history of hubs and devices.Add battery monitoring support. Add http request support. Add Websocket support. Add built-in firmware updater. Add dynamic hubs. |
2.1 | Fix various typos and change instructions for the new C++ API
installation. Add support for Thunderbolt devices under Windows. Add API functions cbrx_find and
cbrx_get_usbtree .Document removal of cbrx_connection_set_password and the addition of its
replacement argument to cbrx_connection_open .Change documentation versioning to align with API version ( api_major .api_minor ).## Known
IssuesEtherSync devices are not supported. Please use the classic API for these. Linux ARMv7 requires latest GCC libraries. Currently only Debian/Ubuntu flavours of Linux are supported. |
Older changes listed here are specific to the historical versions of the API prior to the 2.1 re-write.
Version | Changes |
---|---|
0.20 | Re-brand. |
0.18 | Add “PortInfo.n”, “PortsInfo” and “Health” keys to speed up returning information from API, bump API version to 1.7. |
0.17 | Add “HardwareFlags” key to the Get dictionary to help check on feature sets available. |
0.16 | Add keys to dictionaries to manipulate enabled profiles and bump API version to 1.6. |
0.15 | Add description of new cbrx_connection_getdetail
command. |
0.14 | Add in support for PD-Sync 4 with PD feature set. |
0.13 | Correct python example for reboot. Add in need to install python-setuptools |
0.12 | Add options and description for Docks . |
0.11 | Add section on controlling LEDs. |
0.10 | Add commands to allow specifying remote devices explicitly and to clear the list of remote devices. |
0.9 | Add section on use of sockets. Add section on handle timeouts. Add support for EtherSync. Fixed incorrect value for default listening port. Improved response times. Added USB event driven updates |
0.8 | Add reference to minimum supported firmware level. Fixed current api version returned. Add leds, USBStrings and Attached commands. |
0.7 | Remove listed requirement for libgtk from Linux install
section. Add install instructions for OS X. Fix typo mistake Reset -> Reboot in one place.Add mode command to control all ports at once. Fix typo in Minimal Example Python code. Remove erroneous params in cbrx_apiversion
JSON example. |
0.6 | API now allows multiple requests in a single TCP connection. |
0.5pre11 | New keys added to Get Dictionary:Key.1 ,
Key.2 , Key.3 ,
SecurityArmed .New keys added to Set Dictionary: SecurityArmed . |
0.5pre10 | New keys added to Set Dictionary:RemoteControl ,
Beep , ClearLCD ,
LCDText.row.column , Port.n.led1 ,
Port.n.led2 , Port.n.led3 . |
0.5pre9 | Linux now supports Port.n.PID and
Port.n.VID .Windows installer available. cbrx_connection_id_to_os_reference call
added.Unit id is now based on the serial number of the Cambrionix unit. New keys added to Get Dictionary for properties of an attached USB device: Port.n.SerialNumber ,
Port.n.Manufacturer , Port.n.Description . |
0.5pre8 | Initial public revision |