JSDRV API
- group jsdrv_api
The Joulescope driver host application interface.
This API is based upon a distributed publish-subscribe (PubSub) implementation. The system is arranged as a hierarchical set of topics which have values. Devices expose topics that control and configure operation. Devices also publish the measured data to topics for consumption by the host application.
The host code can set topic values using jsdrv_publish(). Host code can subscribe to topic value changes using jsdrv_subscribe(). This driver will then call the registered subscriber callback for each change on a matching topic. When the host code calls jsdrv_subscribe() with flags (JSDRV_SFLAG_RETAIN | JSDRV_SFLAG_PUB), then the driver immediately provides the retained values to synchronize the host state.
This implementation provides several nice features:
Multiple value data types including integers, floats, str, json, binary
Retained values
Topic metadata for automatically populating user interfaces.
Thread-safe, in-order operation. The driver provides thread-safe synchronous publish with timeout. However, subscriber callbacks are always invoked from the internal PubSub thread, and the host code is responsible for resynchronization.
Guaranteed in-order topic traversal for retained messages based upon creation order.
Device connection options:
connect and restore default settings
connect and resume using existing device settings.
Topic names use a hierarchical naming convention. Topics associated with a device start with a prefix: {p} = {backend}/{model}/{serial_number}
{backend}: 1 character backend identifier 0-9, a-z, A-Z.
{model}: The device model number, such as js220.
{serial_number}: The device serial number string.
The rest of the topic is also hierarchical, and the following characters are reserved:
Topics that start with ‘_’ or ‘@’ are directed only to the central PubSub instance within the driver itself./?#$'"`&@%
Topics are presumed to have retained values unless the subtopic starts with the character ‘!’.
Topics with the following suffix characters have special meanings:
’’: metadata request (value should be NULL)
’$’: metadata response
’?’: query request (value should be NULL)
’&’: query response
’#’: return code. Value is i32 return code. 0=success.
Note that the topic owner will respond to jsdrv_publish operations with a return code to allow for fully synchronous operation.
The metadata values are JSON-formatted strings with the following data structure:
dtype: one of [str, json, bin, f32, f64, u8, u16, u32, u64, i8, i16, i32, i64]
brief: A brief string description (recommended).
detail: A more detailed string description (optional).
default: The recommended default value (optional).
options: A list of options, where each option is each a flat list of: [value [, alt1 [, …]]] The alternates must be given in preference order. The first value must be the value as dtype. The second value alt1 (when provided) is used to automatically populate user interfaces, and it can be the same as value. Additional values will be interpreted as equivalents.
range: The list of [v_min, v_max] or [v_min, v_max, v_step]. Both v_min and v_max are inclusive. v_step defaults to 1 if omitted.
format: Formatting hints string:
version: The u32 dtype should be interpreted as major8.minor8.patch16.
flags: A list of flags for this topic. Options include:
ro: This topic cannot be updated.
hide: This topic should not appear in the user interface.
dev: Developer option that should not be used in production.
Defines
-
JSDRV_PAYLOAD_LENGTH_MAX
The maximum size for normal PubSub messages.
-
JSDRV_STREAM_HEADER_SIZE
The header size of jsdrv_stream_signal_s before the data field.
-
JSDRV_STREAM_DATA_SIZE
The size of data in jsdrv_stream_signal_s.
-
JSDRV_TIMEOUT_MS_DEFAULT
The recommended default timeout.
-
JSDRV_TIMEOUT_MS_INIT
The recommended default jsdrv_initialize() timeout.
Typedefs
-
typedef void (*jsdrv_subscribe_fn)(void *user_data, const char *topic, const struct jsdrv_union_s *value)
Function called on topic updates.
This function will be called from the Joulescope driver frontend thread. The function is responsible for performing any resynchronization to an application target thread, if needed. However, the value only remains valid for the duration of the callback. Any binary or string data must be copied!
- Param user_data:
The arbitrary user data.
- Param topic:
The topic for this update.
- Param value:
The value for this update.
Enums
-
enum jsdrv_payload_type_e
The payload type for jsdrv_union_s.app.
Values:
-
enumerator JSDRV_PAYLOAD_TYPE_UNION
-
enumerator JSDRV_PAYLOAD_TYPE_STREAM
-
enumerator JSDRV_PAYLOAD_TYPE_STATISTICS
-
enumerator JSDRV_PAYLOAD_TYPE_BUFFER_INFO
-
enumerator JSDRV_PAYLOAD_TYPE_BUFFER_REQ
-
enumerator JSDRV_PAYLOAD_TYPE_BUFFER_RSP
-
enumerator JSDRV_PAYLOAD_TYPE_UNION
-
enum jsdrv_element_type_e
The element base type for streaming data.
See also
Values:
-
enumerator JSDRV_DATA_TYPE_UNDEFINED
-
enumerator JSDRV_DATA_TYPE_INT
-
enumerator JSDRV_DATA_TYPE_UINT
-
enumerator JSDRV_DATA_TYPE_FLOAT
-
enumerator JSDRV_DATA_TYPE_UNDEFINED
-
enum jsdrv_field_e
The signal field type for streaming data.
See also
Values:
-
enumerator JSDRV_FIELD_UNDEFINED
-
enumerator JSDRV_FIELD_CURRENT
-
enumerator JSDRV_FIELD_VOLTAGE
-
enumerator JSDRV_FIELD_POWER
-
enumerator JSDRV_FIELD_RANGE
-
enumerator JSDRV_FIELD_GPI
-
enumerator JSDRV_FIELD_UART
-
enumerator JSDRV_FIELD_RAW
-
enumerator JSDRV_FIELD_UNDEFINED
-
enum jsdrv_time_type_e
The time specification type.
Values:
-
enumerator JSDRV_TIME_UTC
Time in i64 34Q30 UTC. See jsdrv/time.h.
-
enumerator JSDRV_TIME_SAMPLES
Time in sample_ids for the corresponding channel.
-
enumerator JSDRV_TIME_UTC
-
enum jsdrv_buffer_response_type_e
The buffer response type.
Values:
-
enumerator JSDRV_BUFFER_RESPONSE_SAMPLES
Data contains samples.
-
enumerator JSDRV_BUFFER_RESPONSE_SUMMARY
Data contains summary statistics.
-
enumerator JSDRV_BUFFER_RESPONSE_SAMPLES
-
enum jsdrv_subscribe_flag_e
The subscriber flags for jsdrv_subscribe().
Values:
-
enumerator JSDRV_SFLAG_NONE
No flags (always 0).
-
enumerator JSDRV_SFLAG_RETAIN
Immediately forward retained PUB and/or METADATA, depending upon JSDRV_PUBSUB_SFLAG_PUB and JSDRV_PUBSUB_SFLAG_METADATA_RSP.
-
enumerator JSDRV_SFLAG_PUB
Receive normal topic publish.
-
enumerator JSDRV_SFLAG_METADATA_REQ
Subscribe to receive metadata requests like “$” and “a/b/$”.
-
enumerator JSDRV_SFLAG_METADATA_RSP
Subscribe to receive metadata responses like “a/b/c$.
-
enumerator JSDRV_SFLAG_QUERY_REQ
Subscribe to receive query requests like “?” and “a/b/?”.
-
enumerator JSDRV_SFLAG_QUERY_RSP
Subscribe to receive query responses like “a/b/c?”.
-
enumerator JSDRV_SFLAG_RETURN_CODE
Subscribe to receive return code messages like “a/b/c#”.
-
enumerator JSDRV_SFLAG_NONE
-
enum jsdrv_device_open_mode_e
The driver mode for device open.
Values:
-
enumerator JSDRV_DEVICE_OPEN_MODE_DEFAULTS
Restore the device to its default, power-on state.
-
enumerator JSDRV_DEVICE_OPEN_MODE_RESUME
Update the driver with the device’s existing state.
-
enumerator JSDRV_DEVICE_OPEN_MODE_RAW
Low-level open only, for use by internal tools.
-
enumerator JSDRV_DEVICE_OPEN_MODE_DEFAULTS
Functions
-
int32_t jsdrv_initialize(struct jsdrv_context_s **context, const struct jsdrv_arg_s *args, uint32_t timeout_ms)
Initialize the Joulescope driver (synchronous).
- Parameters:
context – [out] The Joulescope driver context for future API calls.
args – The initialization arguments or NULL. The argument list is terminated with an argument with an empty string for topic.
timeout_ms – This function is always blocking and waits for up to timeout_ms for the operation to complete. When 0, use the default timeout [recommended]. When nonzero, override the default timeout.
- Returns:
0 or error code.
-
void jsdrv_finalize(struct jsdrv_context_s *context, uint32_t timeout_ms)
Finalize the Joulescope driver (synchronous).
This function releases all Joulescope driver resources including memory and threads.
This function must not be called from the driver frontend thread. Therefore, do not call this function directly from a subscriber callback.
- Parameters:
context – The context from jsdrv_initialize().
timeout_ms – This function is always blocking and waits for up to timeout_ms for the operation to complete. When 0, use the default timeout [recommended]. When nonzero, override the default timeout.
-
int32_t jsdrv_publish(struct jsdrv_context_s *context, const char *topic, const struct jsdrv_union_s *value, uint32_t timeout_ms)
Publish a new value.
- Parameters:
context – The Joulescope driver context.
topic – The topic to publish.
value – The new topic value.
timeout_ms – When 0, publish asynchronously without awaiting the result. When nonzero, block awaiting the return code message.
- Returns:
0 or error code. All calls may return JSDRV_ERROR_PARAMETER_INVALID. Each topic may return other error codes.
-
int32_t jsdrv_query(struct jsdrv_context_s *context, const char *topic, struct jsdrv_union_s *value, uint32_t timeout_ms)
Query a retained value.
- Parameters:
context – The Joulescope driver context.
topic – The topic to query.
value – [inout] The topic value. For string, JSON, and binary values, the provided value must be initialized with an allocated buffer. The value will be copied into this buffer or return JSDRV_ERROR_TOO_SMALL. If provided, this buffer will be ignored for other value types.
timeout_ms – This function is always blocking and waits for up to timeout_ms for the operation to complete. When 0, use the default timeout [recommended]. When nonzero, override the default timeout.
- Returns:
0 or error code. All calls may return JSDRV_ERROR_PARAMETER_INVALID and JSDRV_ERROR_TIMED_OUT.
-
int32_t jsdrv_subscribe(struct jsdrv_context_s *context, const char *topic, uint8_t flags, jsdrv_subscribe_fn cbk_fn, void *cbk_user_data, uint32_t timeout_ms)
Subscribe to topic updates.
Synchronous, blocking subscription is most useful when flags contains JSDRV_SFLAG_RETAIN. The operation will not complete until cbk_fn() is called with all retained values.
- Parameters:
context – The Joulescope driver context.
topic – The subscription topic. The cbk_fn will be called whenever this topic or a child is updated.
flags – The jsdrv_subscribe_flag_e bitmap. 0 (JSDRV_SFLAG_NONE) for no flags.
cbk_fn – The function to call with topic updates. When called, this function will be invoked from the Joulescope driver thread. The function must NOT call jsdrv_finalize() or jsdrv_wait().
cbk_user_data – The arbitrary data provided to cbk_fn.
timeout_ms – When 0, subscribe asynchronously. When nonzero, block awaiting the subscription operation to complete.
- Returns:
0 or error code.
-
int32_t jsdrv_unsubscribe(struct jsdrv_context_s *context, const char *topic, jsdrv_subscribe_fn cbk_fn, void *cbk_user_data, uint32_t timeout_ms)
Unsubscribe to topic updates.
Most callers will want to use blocking, synchronous unsubscribe. Blocking unsubscribe ensures that cbk_fn() will not be called when this function returns. With asynchronous unsubscribe, cbk_fn() may be called for some indefinite number of times and duration until the unsubscribe request is handled internally.
See also
See also
- Parameters:
context – The Joulescope driver context.
topic – The subscription topic for unsubscription.
cbk_fn – The previous subscribed function.
cbk_user_data – The arbitrary data provided to cbk_fn which must match the value provided to jsdrv_subscribe().
timeout_ms – When 0, unsubscribe asynchronously. When nonzero, block awaiting the unsubscribe operation to complete.
- Returns:
0 or error code.
-
int32_t jsdrv_unsubscribe_all(struct jsdrv_context_s *context, jsdrv_subscribe_fn cbk_fn, void *cbk_user_data, uint32_t timeout_ms)
Unsubscribe from all topic updates (asynchronous).
Most callers will want to use blocking, synchronous unsubscribe. See jsdrv_unsubscribe() for details.
See also
- Parameters:
context – The Joulescope driver context.
cbk_fn – The previous subscribed function.
cbk_user_data – The arbitrary data provided to cbk_fn which must match the value provided to jsdrv_subscribe().
timeout_ms – When 0, unsubscribe asynchronously. When nonzero, block awaiting the unsubscribe operation to complete.
- Returns:
0 or error code.
-
int32_t jsdrv_open(struct jsdrv_context_s *context, const char *device_prefix, int32_t mode)
Open a device.
This is a convenience function that wraps a single call to jsdrv_publish() with an i32 value. Language wrappers should not wrap this function and instead call jsdrv_publish() directly.
- Parameters:
context – The Joulescope driver context.
device_prefix – The device prefix string.
mode – The jsdrv_device_open_mode_e.
- Returns:
0 or error code.
-
int32_t jsdrv_close(struct jsdrv_context_s *context, const char *device_prefix)
Close a device.
This is a convenience function that wraps a single call to jsdrv_publish(). Language wrappers should not wrap this function and instead call jsdrv_publish() directly.
- Parameters:
context – The Joulescope driver context.
device_prefix – The device prefix string.
- Returns:
0 or error code.
-
void jsdrv_calibration_hash(const uint32_t *msg, uint32_t length, uint32_t *hash)
Compute the calibration hash.
- Parameters:
msg[in] – The calibration message.
length[in] – The length of message in bytes which must be a multiple of 32 bytes.
hash[out] – The u32[16] hash of the message. The total length is u32 x 16 = 64-byte = 512 bit.
-
struct jsdrv_stream_signal_s
- #include <jsdrv.h>
A contiguous, uncompressed sample block for a channel.
Public Members
-
uint64_t sample_id
the starting sample id, which increments by decimate_factor.
-
uint8_t field_id
jsdrv_field_e
-
uint8_t index
The channel index within the field.
-
uint8_t element_type
jsdrv_element_type_e
-
uint8_t element_size_bits
The element size in bits.
-
uint32_t element_count
size of data in elements
-
uint32_t sample_rate
The frequency for sample_id.
-
uint32_t decimate_factor
The decimation factor from sample_id to data samples.
-
struct jsdrv_time_map_s time_map
The time map between sample_id (before decimate_factor) and UTC.
-
uint8_t data[JSDRV_STREAM_DATA_SIZE]
The channel data.
-
uint64_t sample_id
-
struct jsdrv_statistics_s
- #include <jsdrv.h>
The payload data structure for statistics updates.
Public Members
-
uint8_t version
The version, only 1 currently supported.
-
uint8_t rsv1_u8
Reserved = 0.
-
uint8_t rsv2_u8
Reserved = 0.
-
uint8_t decimate_factor
The decimate factor from sample_id to calculated samples = 2.
-
uint32_t block_sample_count
Samples used to compute this block, in decimated samples.
-
uint32_t sample_freq
The samples per second for *_sample_id (undecimated)
-
uint32_t rsv3_u8
Reserved = 0.
-
uint64_t block_sample_id
First sample in this block’s statistics computation.
-
uint64_t accum_sample_id
First sample in the integration statistics computation.
-
double i_avg
The average current over the block.
-
double i_std
The standard deviation of current over the block.
-
double i_min
The minimum current value in the block.
-
double i_max
The maximum current value in the block.
-
double v_avg
The average voltage over the block.
-
double v_std
The standard deviation of voltage over the block.
-
double v_min
The minimum voltage value in the block.
-
double v_max
The maximum voltage value in the block.
-
double p_avg
The average power over the block.
-
double p_std
The standard deviation of power over the block.
-
double p_min
The minimum power value in the block.
-
double p_max
The maximum power value in the block.
-
double charge_f64
The charge (integral of current) from accum_sample_id as a 64-bit float.
-
double energy_f64
The energy (integral of power) from accum_sample_id as a 64-bit float.
-
uint64_t charge_i128[2]
The charge (integral of current) from accum_sample_id as a 128-bit signed integer with 2**-31 scale.
-
uint64_t energy_i128[2]
The energy (integral of power) from accum_sample_id as a 128-bit signed integer with 2**-31 scale.
-
struct jsdrv_time_map_s time_map
The time map between sample_id and UTC.
-
uint8_t version
-
struct jsdrv_time_range_utc_s
- #include <jsdrv.h>
A UTC-defined time range.
Times are int64 34Q30 in UTC from the epoch. See jsdrv/time.h.
-
struct jsdrv_time_range_samples_s
- #include <jsdrv.h>
A sample_id-defined time range.
Times are in uint64_t sample_ids for the corresponding channel.
-
struct jsdrv_buffer_info_s
- #include <jsdrv.h>
The signal buffer information.
This structure contains both the size and range. The size is populated immediately, even if the buffer is still empty. As the buffer contents grows, the buffer range will approach the buffer size. When the buffer is full, the range will be close to the size. The range when full is not required to be the entire size to allow for buffering optimizations.
Public Members
-
uint8_t version
The response format version == 1.
-
uint8_t rsv1_u8
Reserved, set to 0.
-
uint8_t rsv2_u8
Reserved, set to 0.
-
uint8_t rsv3_u8
Reserved, set to 0.
-
uint8_t field_id
jsdrv_field_e
-
uint8_t index
The channel index within the field.
-
uint8_t element_type
jsdrv_element_type_e
-
uint8_t element_size_bits
The element size in bits.
-
char topic[JSDRV_TOPIC_LENGTH_MAX]
The source topic that provides jsdrv_stream_signal_s.
-
int64_t size_in_utc
The total buffer size in UTC time.
-
uint64_t size_in_samples
The total buffer size in samples.
-
struct jsdrv_time_range_utc_s time_range_utc
In UTC time.
-
struct jsdrv_time_range_samples_s time_range_samples
In sample time.
-
struct jsdrv_time_map_s time_map
The map between samples and utc time.
-
uint8_t version
-
union jsdrv_buffer_request_time_range_u
- #include <jsdrv.h>
The time range union for buffer requests.
-
struct jsdrv_buffer_request_s
- #include <jsdrv.h>
Request data from the streaming sample buffer.
To make a sample request that returns jsdrv_buffer_sample_response_s, only specify end or length. Set the unused value to zero.
If both end and length are specified, then the request may return jsdrv_buffer_summary_response_s. However, if the specified increment is less than or equal to one sample duration, then the request will return jsdrv_buffer_sample_response_s.
For JSDRV_TIME_UTC with end and length > 1, the time increment between samples is: time_incr = (time_end - time_start) / (length - 1)
Using python, the x-axis time is then: x = np.linspace(time_start, time_end, length, dtype=np.int64)
For JSDRV_TIME_SAMPLES with end and length > 1, the sample increment between samples is: sample_id_incr = (sample_id_end - sample_id_start) / (length - 1)
The buffer implementation may deduplicate requests using the combination rsp_topic and rsp_id.
Public Members
-
uint8_t version
The request format version == 1.
-
int8_t time_type
jsdrv_time_type_e
-
uint8_t rsv1_u8
Reserved, set to 0.
-
uint8_t rsv2_u8
Reserved, set to 0.
-
uint32_t rsv3_u32
Reserved, set to 0.
-
char rsp_topic[JSDRV_TOPIC_LENGTH_MAX]
The topic for this response.
-
int64_t rsp_id
The additional identifier to include in the response.
-
uint8_t version
-
struct jsdrv_summary_entry_s
- #include <jsdrv.h>
A single summary statistics entry.
-
struct jsdrv_buffer_response_s
- #include <jsdrv.h>
The response to jsdrv_buffer_request_s produced by the memory buffer.
The response populates both info.time_range_utc and info.time_range_samples. Both length values are equal, and specify the number of returned data samples. For response_type JSDRV_BUFFER_RESPONSE_SUMMARY, the data is jsdrv_summary_entry_s[info.time_range_utc.length]. info.element_type is JSDRV_DATA_TYPE_UNDEFINED and info.element_size_bits is sizeof(jsdrv_summary_entry_s) * 8.
For response_type JSDRV_BUFFER_RESPONSE_SAMPLES, the data type depends upon info.element_type and info.element_size_bits.
Public Members
-
uint8_t version
The response format version == 1.
-
uint8_t response_type
jsdrv_buffer_response_type_e
-
uint8_t rsv1_u8
Reserved, set to 0.
-
uint8_t rsv2_u8
Reserved, set to 0.
-
uint32_t rsv3_u32
Reserved, set to 0.
-
int64_t rsp_id
The value provided to jsdrv_buffer_request_s.
-
struct jsdrv_buffer_info_s info
The response information.
-
uint64_t data[]
The response data.
The data type for the response varies. Unfortunately, C does not support flexible arrays in union types. Your code should cast the data to the appropriate type. Use info.time_range_samples.length for the number of data elements in this response data.
For response_type JSDRV_BUFFER_RESPONSE_SUMMARY, the data is jsdrv_summary_entry_s[info.time_range_samples.length].
For response_type JSDRV_BUFFER_RESPONSE_SAMPLES, the data is defined by info.element_type and info.element_size_bits.
-
uint8_t version
-
struct jsdrv_arg_s
- #include <jsdrv.h>
The initialization argument structure.
Public Members
-
const char *topic
The argument name.
-
struct jsdrv_union_s value
The argument value.
-
const char *topic