Driver

class pyjoulescope_driver.DeviceContext(driver, device_path)

An open device returned by Driver.open().

The topic arguments are relative to the device path, such as “s/i/range/mode”. Call close() or exit the context to unsubscribe all subscriptions made through this instance and then close the device.

close(timeout=None)

Unsubscribe all subscriptions made through this instance, and then close the device. Calling close again does nothing.

See Driver.close().

publish(topic, value, timeout=None)

Publish a value. See Driver.publish().

publish_and_wait(publish_topic, publish_value, response_topic, timeout=None, match=None)

Publish and wait for a response. See Driver.publish_and_wait().

query(topic, timeout=None)

Query a value. See Driver.query().

subscribe(topic, flags, fn, timeout=None)

Subscribe to a topic. See Driver.subscribe().

close() unsubscribes the subscription, if still active.

Returns:

The SubscribeContext.

topic(topic)

Get the absolute topic.

Parameters:

topic – The topic relative to the device path.

Returns:

The absolute topic, “{device_path}/{topic}”.

unsubscribe(topic, fn, timeout=None)

Unsubscribe from a topic. See Driver.unsubscribe().

class pyjoulescope_driver.Driver

The Joulescope driver class.

Parameters:

timeout – The optional timeout for open. None (default) uses the default timeout.

The native driver log forwards to the Python “jsdrv” logger at log_level, which defaults to “error”.

The application must finalize each Driver instance, either with a context manager or by calling finalize() directly. Finalize stops the driver threads and closes the devices that the instance opened. A Driver that is never finalized keeps its threads running and its devices open, which is a program bug. Typical usage:

from pyjoulescope_driver import Driver

with Driver() as d:
    device_path = d.find_one_device('js320', brand='joulescope')
    with d.open(device_path, mode='restore') as device:
        device.publish('s/i/range/mode', 'auto')
        with device.subscribe('s/stats/value', 'pub', on_statistics):
            time.sleep(1.0)

Use device_paths(), find_devices() and find_one_device() to select devices, and device_watch() to track device additions and removals. open() returns a DeviceContext, and subscribe() returns a SubscribeContext.

The driver thread invokes the subscriber callbacks and completes every command, so a callback cannot wait on the driver. A Driver method called from a callback is forced asynchronous, whatever its timeout: publish(), subscribe() and unsubscribe() return at once and report any error only to the log, and query() returns a zeroed value. Use is_driver_thread() to tell the two cases apart, and defer work that needs a result, such as open(), to another thread.

close(device_prefix, timeout=None)

Close an attached device.

Parameters:
  • device_prefix – The prefix name for the device.

  • timeout – The timeout in seconds. None uses the default timeout.

device_paths(specs=None, brand=None, timeout=None)

List the currently connected devices.

Parameters:
  • specs – The device specifications. None (default) lists all devices. See device_filter.find().

  • brand – The case-insensitive brand, such as “Joulescope”. None (default) lists all brands.

  • timeout – The timeout in seconds. None (default) uses the default timeout.

Returns:

The sorted list of matching DevicePath instances, which are str instances.

Raises:
  • TypeError – If specs or brand has an invalid type.

  • ValueError – If brand is not supported.

Before 2.5.0, the first positional argument was timeout. A numeric specs is still treated as timeout, with a DeprecationWarning.

device_watch(on_add, on_remove, specs=None, brand=None, timeout=None)

Watch for matching devices.

Parameters:
  • on_add – The callable(device_path) called with the DevicePath for each added device. Before returning, this method calls on_add for each connected device.

  • on_remove – The callable(device_path) called with the DevicePath for each removed device.

  • specs – The device specifications. None (default) matches all devices. See device_filter.find().

  • brand – The case-insensitive brand, such as “Joulescope”. None (default) matches all brands.

  • timeout – The timeout in seconds. None (default) uses the default timeout.

Returns:

The SubscribeContext. Call unsubscribe() or exit its context to stop watching.

This method calls on_add for the connected devices from the calling thread, so these on_add calls may use any Driver method. Afterwards, the driver thread calls on_add and on_remove, once for each device addition and removal, in order. Driver calls from these callbacks are forced asynchronous, see is_driver_thread(), so defer work that needs a result, such as open(), to another thread.

finalize(timeout=None)

Finalize the driver and release all resources.

Finalize first closes each device that this instance opened and that is still connected, ignoring close errors. It then stops the driver, which stops all subscriptions. Afterwards, close, unsubscribe and unsubscribe_all do nothing, and the other methods raise RuntimeError. Exiting a with Driver() as d: block calls finalize.

Parameters:

timeout – The timeout in seconds. None (default) uses the driver’s finalize timeout, which allows time for every device and backend thread to exit.

find_devices(specs=None, brand=None, timeout=None)

Find the connected devices.

This method is an alias for device_paths(), which reads better next to find_one_device().

find_one_device(specs=None, brand=None, timeout=None)

Find exactly one connected device.

Parameters:
  • specs – The device specifications. None (default) matches all devices. See device_filter.find().

  • brand – The case-insensitive brand, such as “Joulescope”. None (default) matches all brands.

  • timeout – The timeout in seconds. None (default) uses the default timeout.

Returns:

The matching DevicePath.

Raises:

device_filter.DeviceFilterError – If zero or multiple devices match.

is_driver_thread()

Check if the caller is the driver thread.

Returns:

True when called from the driver thread, which invokes the subscriber callbacks. False otherwise, including after finalize().

Driver methods called from the driver thread are forced asynchronous, whatever their timeout. See Driver.

log_level

The current log level.

See LogLevel.

open(device_prefix, mode=None, timeout=None)

Open an attached device.

Parameters:
  • device_prefix – The prefix name for the device.

  • mode –

    The open mode which is one of:

    • ’defaults’: Push state to the device: the host’s retained value for each writable topic when present, else the metadata default.

    • ’restore’: Push nothing; adopt the device’s current state into the host cache.

    • ’raw’: Open the device in raw mode for development or firmware update.

    • None: equivalent to ‘defaults’.

  • timeout – The timeout in seconds. None uses the default open timeout, 3 seconds, which allows a device time to recover from a host that exited without closing it.

Returns:

The DeviceContext for the open device, which closes the device on close() or when used as a context manager:

with d.open(device_path) as device:
    device.publish('s/i/range/mode', 'auto')

Finalize closes all devices that remain open.

publish(topic, value, timeout=None)

Publish a value to a topic.

Parameters:
  • topic – The topic string.

  • value – The value, which must pass validation for the topic.

  • timeout – The timeout in seconds. None (default) uses the default timeout and waits for the return code. 0 does not wait, so publish cannot raise for an invalid topic or value. The driver logs the error at ERROR level to the “jsdrv” logger instead, such as “publish u/js320/8W2A/s/nope failed: 16 NOT_FOUND”. Use a blocking publish when the caller must handle the error.

Raise:

On error.

publish_and_wait(publish_topic, publish_value, response_topic, timeout=None, match=None)

Publish a value and wait for a response on another topic.

Parameters:
  • publish_topic – The topic to publish to.

  • publish_value – The value to publish.

  • response_topic – The topic to subscribe to for the response.

  • timeout – The timeout in float seconds. None (default) uses the default timeout.

  • match – The optional callable(value) that returns True for the expected response. Other responses, such as those for another transaction, are ignored. None (default) accepts the first response.

Returns:

The value received on response_topic.

Raises:

TimeoutError – If no response arrives in time.

query(topic, timeout=None)

Query the value for a topic.

Parameters:
  • topic – The topic name.

  • timeout – The timeout in seconds. None (default) uses the default timeout.

Returns:

The value for the topic.

Raise:

On error.

subscribe(topic, flags, fn, timeout=None)

Subscribe to receive topic updates.

Parameters:
  • self – The driver instance.

  • topic – Subscribe to this topic string.

  • flags –

    The flags or list of flags for this subscription. The flags can be int32 jsdrv_subscribe_flag_e or string mnemonics, which are:

    • pub: Subscribe to normal values

    • pub_retain: Subscribe to normal values and immediately publish all matching retained values. With timeout, this function does not return successfully until all retained values have been published.

    • metadata_req: Subscribe to metadata requests (not normally useful).

    • metadata_rsp: Subscribe to metadata updates.

    • metadata_rsp_retain: Subscribe to metadata updates and immediately publish all matching retained metadata values.

    • query_req: Subscribe to all query requests (not normally useful).

    • query_rsp: Subscribe to all query responses.

    • return_code: Subscribe to all return code responses.

  • fn – The function to call on each publish. Note that python dynamically constructs bound methods. To unsubscribe a method, provide the exact same bound method instance to unsubscribe.

  • timeout – The timeout in float seconds to wait for this operation to complete. None waits the default amount. 0 does not wait and subscription will occur asynchronously.

Returns:

The SubscribeContext, which unsubscribes on unsubscribe() or when used as a context manager:

with d.subscribe(topic, 'pub', fn):
    ...

Raises:

RuntimeError – on subscribe failure.

unsubscribe(topic, fn, timeout=None)

Unsubscribe from a topic.

Parameters:
  • topic – The topic name string.

  • fn – The function previously provided to subscribe().

  • timeout – The timeout in seconds. None (default) uses the default timeout. 0 returns at once, and fn may still be called until the driver thread handles the request.

Raise:

On error.

When this method returns after waiting, fn is no longer called. From a callback, this method cannot wait, see is_driver_thread().

unsubscribe_all(fn, timeout=None)

Unsubscribe a callback from all topics.

Parameters:
  • fn – The function previously provided to subscribe().

  • timeout – The timeout in seconds. None (default) uses the default timeout. 0 returns at once, and fn may still be called until the driver thread handles the request.

Raise:

On error.

See unsubscribe().

class pyjoulescope_driver.ElementType

The element type enumeration.

class pyjoulescope_driver.ErrorCode

The error code enumeration.

class pyjoulescope_driver.Field

The field enumeration.

class pyjoulescope_driver.LogLevel

The log level enumeration.

class pyjoulescope_driver.MemClient(driver, device_path, cmd_topic, target=0)[source]

Generic mb_stdmsg_mem_s protocol client.

Parameters:
  • driver – The Driver instance.

  • device_path – The device path (e.g. ‘u/js320/000000’).

  • cmd_topic – The memory command sub-topic (e.g. ‘s/flash/!cmd’).

  • target – The target memory region ID (0-255).

cmd(op, offset=0, length=0, data=b'', timeout_ms=5000, target=None)[source]

Send a memory command and wait for the response.

Parameters:
  • op – The memory operation (MEM_OP_READ, etc.).

  • offset – The byte offset within the target region.

  • length – The operation length in bytes.

  • data – The payload data for write operations.

  • timeout_ms – The device-side timeout in milliseconds.

  • target – Override the instance target for this call.

Returns:

The response data bytes.

Raises:
  • TimeoutError – If no response within timeout.

  • RuntimeError – If the device returns a non-zero status.

erase_64k(offset)[source]

Erase a 64 KB block.

Parameters:

offset – The block-aligned byte offset.

read(offset, length)[source]

Read data in 256-byte page chunks.

Parameters:
  • offset – The starting byte offset.

  • length – The number of bytes to read.

Returns:

The read bytes.

read_personality()[source]

Read the public mb_personality_app_s from the sys task.

The MemClient must be pointed at the sys task command topic (e.g. MemClient(driver, device, 'c/sys/!cmd')).

Returns:

A dict with the public personality fields.

Raises:

ValueError – If the response is too short.

write_pages(offset, data)[source]

Write data in 256-byte page chunks.

Parameters:
  • offset – The starting byte offset.

  • data – The bytes to write.

write_verify(offset, data, retries=3)[source]

Erase, write, and verify with retries.

Parameters:
  • offset – The flash byte offset.

  • data – The data to write.

  • retries – Number of attempts before raising.

Raises:

RuntimeError – If verification fails after all retries.

write_verify_records(records, retries=3)[source]

Erase, write, and verify multiple records with retries.

Parameters:
  • records – The list of (offset, data) pairs.

  • retries – Number of attempts before raising.

Raises:

RuntimeError – If verification fails after all retries.

class pyjoulescope_driver.StdMsg[source]

Binary value published as JSDRV_UNION_STDMSG.

Use this instead of bytes when publishing a value that starts with an mb_stdmsg_header_s so the device receives it as MB_VALUE_STDMSG.

class pyjoulescope_driver.SubscribeContext(driver, subscriptions)

The subscriptions returned by Driver.subscribe().

Call unsubscribe() or exit the context to unsubscribe. After Driver.finalize(), unsubscribe does nothing.

extend(other)

Move the subscriptions from another SubscribeContext into this one.

unsubscribe(timeout=None)

Unsubscribe. Calling unsubscribe again does nothing.

class pyjoulescope_driver.SubscribeFlags

The available subscribe flags.

class pyjoulescope_driver.TimeMap

Python wrapper for jsdrv_tmap_s instance.

Each instance owns its underlying jsdrv_tmap_s. TimeMap values returned from driver responses are independent snapshots; copy() and deepcopy() produce further independent instances.

time_map_get(index=None)

Get the time map data.

Parameters:

index –

The index for the time map which is one of: - None: return all time maps in the instance. - int index: Return only this index. - (int start_index, int end_index): Return this range.

start_index is inclusive, end_index is exclusive.

Returns:

Return an np.ndarray with the the named columns [‘offset_time’, ‘offset_counter’, ‘counter_rate’]. Access as either a[0][‘offset_counter’] or a[0][1].