Client API Documentation#
Connection Function#
- pingthings.connect(profile=None, endpoint=None, apikey=None)#
Connect to the timeseries platform.
Tip
Security best practice
To prevent accidental leakage of user credentials by hardcoded apikeys, this option has been removed from the function argument. Your apikey MUST be included in the environment variable
$BTRDB_API_KEY, and is set by default when you login to the PredictiveGrid JupyterHub environment.Tip
Connecting to the platform for commercial customers
If you are a commercial customer and are using the PingThings JupyterHub/Lab environment to work with the timeseries platform, the relevant connection information has already been added to your session in the form of environment variables. All you need to do to connect to the platform is the following:
import pingthings as pt conn = pt.timeseries.connect()
Warning
Choosing a concurrency limit
The default concurrency limit is defined in
pingthings.timeseries.constants. If the environment variable is not set, it will use this default value. Using a large concurrency limit has the ability to cause large memory consumption, and if the job gets killed, it can also lead to a hard to kill zombie process. Most users will probably be fine with the default concurrency limit, but feel free to explore larger values.- Parameters:
profile – The name of a profile containing the required connection information as found in the user’s predictive grid credentials file
${HOME}/.predictivegrid/credentials.yaml.endpoint – The address and port of the cluster to connect to, e.g.
192.168.1.1:4411, if not set, will look for the environment variable$BTRDB_ENDPOINTSconcurrency_limit – The maximum number of concurrent database requests to have in flight at any one time, if not set, will be inferred from environment variable
$PINGTHINGS_CONCURRENCY_LIMITor the default limit defined inpingthings.timeseries.constants.DEFAULT_CONCURRENCY_LIMIT.
- Returns:
A timeseries client.
Examples
Connecting to the timeseries platform as a commercial customer in the PingThings provided JupyterHub/Lab environment. This behavior also works if you have the environment variables set, refer to the above docstring for more information.
import pingthings as pt conn = pt.timeseries.connect()
Connecting to the platform when you have a populated
${HOME}/.predictivegrid/credentials.yamlfile with profiles.import pingthings as pt conn = pt.timeseries.connect(profile='my_server')
Client Class#
- class pingthings.Client(timeseries_conn=None, admin_conn=None)#
Bases:
object- add_streams_to_my_collection(my_collection_id, stream_uuids)#
Adds streams to a My Collection. If any of the provided streams are already in the collection, they will be ignored.
- clear_event_type_enforcement(group)#
Clears event type enforcement for a group.
- Parameters:
group – The group to clear enforcement for.
- create(uuid, collection, tags=None, annotations=None)#
Create a new stream with the given uuid and collection name.
- Parameters:
uuid – The UUID for the new stream.
collection – The collection to which the stream belongs.
tags – Tags associated with the stream.
annotations – Annotations for the stream.
- Returns:
The newly created stream.
Note
Required and Allowable Tags/Annotations
The
namefield intagsmust be set and currently alltags/annotationsmust be encoded as strings and two streams can not share both the samecollectionandname.Tip
Available tags in the
streamtablecolumn_name
Description
name
name of the stream
source
Where did the stream come from
device_id
What device is the stream attached to
samples_per_second
What is the nominal report rate of the data, in Hz?
time_precision
How accurate is each timestep (+- nanoseconds)
value_precision
Bit precision
dynamic
Can the timeseries stream send us data at varying report rates?
continuous
Should we expect a continuous stream of data?
description
Additional information about the timeseries stream
alt_name
Additional name that the stream may be referenced by
alt_id
Alternative ID (most likely SignalID from STTP)
norm_factor
A factor to scale the measurement by to normalize. Like “baseKV” for voltage, etc.
scaling_factor
The “m” in y=mx + b factor, line-line scaling factor, etc
bias_factor
The “b” in y=mx+b
hidden
Whether the stream should be presented to non-admin users
- create_device(device)#
Creates a device with fields matching the passed dictionary.
namecan not beNoneor an empty string, two devices can not share the samenameandgeo, andenabled=Trueby default.- Parameters:
device – dictionary with the possible keys and description of expected values below.
- Returns:
A dictionary with the same fields passed with create plus the
device["id"]set
Tip
Available columns in the
devicetablecolumn_name
Description
name
Name of device
device_type
Type of device (DFR/Relay/etc)
description
User readable description
geo
Coordinates, a dict {“latitude”:float,”logitude”:float}
elevation
Elevation of the device, float
alt_id
Alternative id, int
alt_name
Alternative name
enabled
Whether the device is expected to be sending data, bool default: True
owner
Who owns the device
protocol
What protocol the device is using to send data
model_name
The model name of the device
vendor
The company that creates/sells the device
- create_event(start_time, end_time=None, stream_uuids=None, group_names=None, source=None, type=None, message=None, title=None)#
Creates an event.
- Parameters:
start_time – The start time of the event (datetime.datetime or int representing nanoseconds since epoch)
end_time – The end time of the event (optional, datetime.datetime or int representing nanoseconds since epoch).
stream_uuids – List of stream UUIDs (optional)
group_names – List of group names (optional). If not provided, the event will be visible to all groups that the user creating the event is a member of.
source – What created/identified the event? (optional)
type – What kind of event? (optional)
message – Longer form description of the event (optional)
title – A short title for the event (optional)
- Returns:
A dictionary representing the created event.
- create_event_type(group, name, description=None)#
Creates an event type.
- Parameters:
group – The group the event type belongs to.
name – The name of the event type.
description – A description of the event type (optional).
- Returns:
A dictionary representing the created event type.
- create_my_collection(name, description=None, parent_my_collection_uuid=None)#
Creates a new My Collection for the currently authenticated user.
- Parameters:
name – The name of the collection
description – An optional description of the collection
parent_my_collection_uuid – An optional UUID of a different my collection to use as the parent of the new collection
- Returns:
A dictionary representing the newly created My Collection. It will contain the following keys:
uuid: The UUID of the collectionname: The name of the collectiondescription: The description of the collectionparent_my_collection_uuid: The UUID of the parent collection, or an emptystring if there is no parent
stream_uuids: A list of UUIDs of streams that are in the collection
- create_streams(uuids, collection, tags=None, custom_tags=None, annotations=None, custom_annotations=None, names=None)#
- create_unit(name, symbol, base, canonical, source_name)#
Create a new representation of a unit definition in the platform.
Unitsare a main way to assign further meaning to the timeseries stored in the platform. There are usually a handful of defaultunitsprovided with each cluster, however, based on user needs, additional units will need to be included to support the wide range of timeseries added to the platform.- Parameters:
name – Name of the new unit.
symbol – Symbol of the new unit.
base – Multiplicative factor to convert the unit to the canonical representation.
canonical – The “main” unit that this unit can be ultimately converted to.
source_name – List of other potential
namesthat thisunitcan be considered in the platform. For example, if theunitname isdegreesthe source_name could include the following:["deg", "VPHA", "IPHA", "VpHA", "Deg", "DEG"]
- Returns:
Dictionary with fields corresponding to the values in the database.
Examples
>>> unit_def = {"name":"volts", "symbol":"V", "base":1.0, "canonical":"volts", source_name:["VPHM", "voltage", "VOLTS", "VLTGE"]} >>> unit = client.create_unit(**unit_def) >>> print(unit) {'id': 6, 'name': 'volts', 'symbol': 'V', 'canonical': 'volts', 'base': 1.0, 'source_name': ['VPHM', 'voltage', 'VOLTS', 'VLTGE']}
- delete_device(device_id)#
Deletes the device with the specified id
- Parameters:
device_id – Corresponding id of the device to be deleted
- Returns:
None
- delete_event(id)#
Deletes an event by its ID.
- Parameters:
event_id – The ID of the event to delete.
- delete_event_type(id)#
Deletes an event type by its ID.
- Parameters:
id – The ID of the event type to delete.
- delete_my_collection(uuid)#
Deletes a My Collection and all of its child collections. Streams that are contained in the collection or any of its children will NOT be deleted.
- delete_unit(unit_id)#
Remove a unit from the platform.
- Parameters:
unit_id – Integer corresponding to the id of the unit in the database.
- Returns:
None
Examples
>>> client.delete_unit(6)
- get_collection_properties(collection)#
Get properties of a collection.
- Parameters:
collection – The name of the collection.
Examples
Get the retention policy of a collection.
>>> conn.get_collection_properties("bar") {'retention': {'remove_older_than': datetime.timedelta(days=7)}}
- get_device(device_id)#
Returns a device with a matching id in the device table.
- Parameters:
device_id – Integer corresponding to the id of the device in the database.
- Returns:
Dictionary with fields corresponding to the values in the database.
- get_devices(device_ids)#
Returns devices with matching ids in the device table.
- Parameters:
device_ids – List of integers corresponding to the ids of the devices in the database.
- Returns:
Dictionary with fields corresponding to the values in the database.
- get_event(id)#
Retrieves an event by its ID.
- Parameters:
event_id – The ID of the event to retrieve.
- Returns:
A dictionary representing the event, or None if not found.
- get_event_type(id)#
Retrieves an event type by its ID.
- Parameters:
id – The ID of the event type to retrieve.
- Returns:
A dictionary representing the event type.
- get_unit(unit_id)#
Returns a unit with a matching id in the unit table.
- Parameters:
unit_id – Integer corresponding to the id of the unit in the database.
- Returns:
Dictionary with fields corresponding to the values in the unit table.
- info()#
Retrieve information about the server and proxy server the client is connected to.
- Returns:
A dictionary containing server and proxy server information.
- list_collections(prefix=None)#
Returns a list of collection paths using the
prefixargument for filtering.- Parameters:
prefix – Filter collections that start with the string provided, if none passed, will list all collections.
- Returns:
All collections that match the provided prefix.
Examples
Assuming we have the following collections in the platform:
foo,bar,foo/baz,bar/baz>>> conn = pt.connect() >>> conn.list_collections().sort() ["bar", "bar/baz", "foo", "foo/bar"]
>>> conn.list_collections(prefix="foo") ["foo", "foo/bar"]
- list_devices()#
Returns a list of devices the user has permission to see.
- Returns:
Dictionary with keys matching the columns in the device table.
- list_event_types(group=Ellipsis)#
Lists event types, optionally filtered to a single group.
- Parameters:
group – If provided, only return event types for this group. When empty, event types for all of the caller’s groups are returned.
- Returns:
A tuple
(event_types, enforce)whereevent_typesis a list of event type dictionaries andenforceis the group’s enforcement flag (a bool) when a group filter is given, orNonewhen no group filter is provided.
- list_events(start_time=None, end_time=None, source_contains=None, type_contains=None, message_contains=None, limit=100, offset=0, sort_by=Ellipsis, sort_desc=False, title_contains=None, created_by_contains=None, full_text_search=None, stream_uuids=None, include_stream_geos=False)#
Return all events that match the given criteria paginated by
offsetandlimit.- Parameters:
start_time – Events must start at this time or greater than this time.
end_time – Events must end at this time or before this time.
source_contains – Substring case-insensitive filter for the event source.
type_contains – Substring case-insensitive filter for the event type.
message_contains – The event must contain this string subset, this uses a case-insensitive substring search.
limit – How many events to return at once
offset – Pagination offset
sort_by – What event parameter to sort by?
sort_desc – Should the results be returned descending order by the
sort_byparameter?title_contains – Substring case-insensitive filter for the event title.
created_by_contains – Substring case-insensitive filter for the user that created the event.
full_text_search – Substring case-insensitive filter across all text fields (title, message, source, type, created_by).
stream_uuids – If provided, only return events associated with at least one of these stream UUIDs.
include_stream_geos – If True, populate
stream_geoson each returned event with the unique GeoJSON coordinates of associated streams. Defaults to False.
- Returns:
A tuple containing the list of events matching the given criteria and the total count of matching events.
Examples
Find all events that contain the word ‘voltage’ (case insensitive):
>>> AdminClient.list_events(message_contains="voltage")
- list_my_collections()#
Return all custom collections you have created.
- Returns:
All custom collections you have created.
- list_units()#
Returns a list of units generated in the database.
- Returns:
Dictionary with keys matching the columns in the units table.
- remove_streams_from_my_collection(my_collection_id, stream_uuids)#
Removes streams from a My Collection. If any of the provided streams are not in the collection, they will be ignored.
- set_collection_retention(collection, override_per_stream, remove_older_than=None)#
Set retention policy on a collection of streams.
- Parameters:
collection – The name of the collection.
override_per_stream – Whether stream-specific retention policy should be overridden.
remove_older_than – Trim time period - after which the data will get removed. Not specifying this parameter disables the trimming.
Examples
Keep the data for only one week.
>>> conn.set_collection_retention("bar", false, datetime.timedelta(days=7))
- set_event_type_enforcement(group, enforce)#
Enables or disables event type enforcement for a group.
- Parameters:
group – The group to set enforcement for.
enforce – Whether to enforce event types for the group.
- set_retention(uuids, remove_older_than=None)#
Set retention policy on a stream.
- Parameters:
remove_older_than – Trim time period after which the data can be removed. Specifying
Noneor not passing the parameter disables trimming.
Examples
Keep the data for only two hours.
>>> stream.set_retention(datetime.timedelta(hours=2))
- stream_from_uuid(py_uuid)#
Retrieve a stream based on its UUID.
- Parameters:
uuid – The UUID of the stream.
- Returns:
The stream associated with the provided UUID.
- Raises:
TypeError – If the provided
uuidis not a valid UUID
- streams_in_collection(collection=None, is_collection_prefix=None, tags=None, annotations=None)#
Search for streams matching given parameters
- Parameters:
collection – collections to use when searching for streams, case sensitive.
is_collection_prefix – Whether the collection is a prefix of the whole collection name.
tags – The tags to identify the stream.
annotations – The annotations to identify the stream.
- Returns:
The grouping of streams matching given parameters.
- streamset_from_uuids(uuids, fetch_metadata=None)#
Return a
StreamSetfrom an iterable of UUIDs.- Parameters:
uuids – List of stream identifiers
fetch_metadata – Whether to fetch metadata for the streams in the set. Default is True.
Warning
Advanced user feature
Be cautious about using
fetch_metadata=False. Many stream metadata values like collection, name, unit, tags, annotations will not be available, meaning filtering and other operations that require metadata will not work.- Returns:
The
StreamSetassociated with the provided iterable of UUIDs.
- update_device(device, replace=False)#
Updates a
devicewith matchingdevice["id"]using fields matching the passed dictionary.namecan not beNoneor an empty string.- Parameters:
device – dictionary with the possible keys and description of expected values below.
replace – whether to change all unspecified values to
None(device["enabled"]=Trueby default).
- Returns:
Dictionary with the updated fields and original unmodified fields of the device
Note
Update Behavior
This function updates a field if it has been set, otherwise it inserts a new value. Not passing a value for an existing field will not clear the value from that field. For that you must choose
replace=True. Ifreplace=Truenamecan not beNoneor an empty string. Even withreplace=Truegeowill not be set toNone.Tip
Available columns in the
devicetablecolumn_name
Description
id
Internal id of device
name
Name of device
device_type
Type of device (DFR/Relay/etc)
description
User readable description
geo
Coordinates, a dict {“latitude”:float,”logitude”:float}
elevation
Elevation of the device, float
alt_id
Alternative id, int
alt_name
Alternative name
enabled
Whether the device is expected to be sending data, bool default: True
owner
Who owns the device
protocol
What protocol the device is using to send data
model_name
The model name of the device
vendor
The company that creates/sells the device
- update_event_type(id, name=None, description=None)#
Updates an event type.
- Parameters:
id – The ID of the event type to update.
name – The new name of the event type. When omitted or
None, the existing name is left unchanged.description – The new description of the event type. When omitted or
None, the existing description is left unchanged; pass""to clear it.
The underlying RPC is a full replacement, so omitted fields are filled in by first fetching the current event type (a read-modify-write).
- Returns:
A dictionary representing the updated event type.
- update_my_collection(my_collection_id, patch)#
Updates a My Collection with the provided patch.
- Parameters:
my_collection_uuid – The UUID of the collection to update
patch –
A dictionary of fields to update. Only fields contained in the dictionary will be updated; all other fields will remain unchanged.
The list of fields that can be updated are:
name: Must be set to a non-empty stringdescription: Can be set to any string orNoneparent_my_collection_uuid: Can be set to a UUID of a differentMy Collection, or
Noneto make the collection top-level
- Returns:
A dictionary representing the updated My Collection. It will contain the same keys as the
create_my_collectionmethod.
- update_unit(unit)#
Updates a
unit_dictwith matchingidusing fields from the passed dictionary.Modify the
unitwhere theunit_dict['id']is theidnumber of theunityou want to update.Note
Update Behavior
You are not requried to include fields that you want to keep the same. Although including them will not cause issues.
- Parameters:
unit_dict – Dictionary with fields corresponding to the values in the database you want to update
- Returns:
Dictionary with the updated fields and original unmodified fields of the unit
Examples
>>> original_unit = client.get_unit(6) >>> print(original_unit) {'id': 6, 'name': 'volts', 'symbol': 'V', 'canonical': 'volts', 'base': 1.0, 'source_name': ['VPHM', 'voltage', 'VOLTS', 'VLTGE']} >>> updated_unit = {"id":6, "name":"volt"} >>> client.update_unit(updated_unit) {'id': 6, 'name': 'volt', 'symbol': 'V', 'canonical': 'volts', 'base': 1.0, 'source_name': ['VPHM', 'voltage', 'VOLTS', 'VLTGE']}