mnubo SmartObjects Python client
Clone or download
Fetching latest commit…
Cannot retrieve the latest commit at this time.
Permalink
Type Name Latest commit message Commit time
Failed to load latest commit information.
examples
ittests
smartobjects
tests
.gitignore
.travis.yml
CHANGELOG.md
LICENSE
MANIFEST.in
README.md
build.sh
creds.ini.enc
requirements.txt
setup.py
setup.template.html

README.md

mnubo SmartObjects Python client

Build status PyPI

Quickstart

Getting the client library

The client library is available on PyPy.

The client depends on other libraries:

  • requests
  • six
  • tenacity
  • pandas (optional)

Below is an example of how you can install everything:

    
pip install smartobjects requests six tenacity pandas
    

For more information, visit GitHub.

Create a client instance

The following python code can be used to create an instance:

    
key = "<%= clientKey %>"
secret = "<%= clientSecret %>"
url = "<%= url %>"
SmartObjectsClient(key, secret, url)
    

Table of Content

1. Introduction

2. At a glance

3. Requirements

4. Installation & Configuration

5. Usage

6. Need help?


1. Introduction

This package provides a simple Python client to connect to mnubo's SmartObjects platform. It gives access to the most common features of mnubo's REST API. All methods require proper authentication. The MnuboClient object handles authentication under the hood based on the client_id and client_secret arguments.

Methods such as create(), delete(), etc, do not return any value. However if anything is invalid or goes wrong, an exception will be thrown so you know what happened.

See the complete documentation here.

2. At a glance

(optional arguments omitted)

Service Method Summary Example
Owners create(owner) create a new owner simple_workflow.py
update(username, owner) update an existing owner
claim(username, device_id, optional_body) link an existing object to an existing owner simple_workflow.py
unclaim(username, device_id, optional_body) unlink an existing object from an existing owner simple_workflow.py
batch_claim(claims) claim a batch of objects simple_workflow.py
batch_unclaim(unclaims) unclaim a batch of objects simple_workflow.py
create_update(owners) create or update a batch of owners
delete(username) delete an owner
owner_exists(username) check if an owner exists simple_workflow.py
owners_exist(usernames) check if a list of owners exist
Objects create(object) create a new smart object simple_workflow.py
update(device_id, object) update an existing object
create_update(objects) create or update a batch of objects
delete(device_id) delete an object
object_exists(device_id) check if an object exists simple_workflow.py
objects_exist(device_ids) check if a list of objects exist
Events send(events) send a batch of events tagged with multiple devices
send_from_device(device_id, events) send an event tagged with a specific device simple_workflow.py
event_exists(event_id) check if an event exists
events_exist(event_ids) check if list of events exist
Search search(query) performs a search in the platform with the provided JSON query (MQL) simple_workflow.py
validate_query(query) validates a MQL query simple_workflow.py
get_datasets() retrieves the list of datasets available for this account simple_workflow.py
Model export() fetches the model in the current zone model_workflow.py
get_timeseries() fetches the timeseries in the current zone
get_object_attributes() fetches the object attributes in the current zone
get_owner_attributes() fetches the owner attributes in the current zone
get_event_types() fetches the event types in the current zone
get_object_types() fetches the object typesin the current zone

The API in sandbox and production is mostly the same. Only the modeler API is different in sandbox. Here are the sandbox only operations that are available on the modeler API:

Entity Method Summary Example
Timeseries model.sandbox_ops.timeseries_ops.createOne create one timeseries in sandbox model_workflow.py
model.sandbox_ops.timeseries_ops.create create multiple timeseries in sandbox
model.sandbox_ops.timeseries_ops.update update a sandbox timeseries
model.sandbox_ops.timeseries_ops.deploy deploy a sandbox timeseries in production model_workflow.py
model_workflow.py
Object Attributes model.sandbox_ops.object_attributes_ops_ops.createOne create one object attribute in sandbox
model.sandbox_ops.object_attributes_ops_ops.create create multiple object attributes in sandbox
model.sandbox_ops.object_attributes_ops_ops.update update a sandbox object attribute
model.sandbox_ops.object_attributes_ops_ops.deploy deploy a sandbox object attribute in production model_workflow.py
model_workflow.py
Owner Attributes model.sandbox_ops.owner_attributes_ops.createOne create one owner attribute in sandbox
model.sandbox_ops.owner_attributes_ops.create create multiple owner attributes in sandbox
model.sandbox_ops.owner_attributes_ops.update update a sandbox owner attribute
model.sandbox_ops.owner_attributes_ops.deploy deploy a sandbox owner attribute in production model_workflow.py
Event Types model.sandbox_ops.event_types_ops.createOne create one event type model_workflow.py
model.sandbox_ops.event_types_ops.create create multiple event types
model.sandbox_ops.event_types_ops.update update a event type
model.sandbox_ops.event_types_ops.delete delete a sandbox event type
Object Types model.sandbox_ops.object_types_ops.createOne create one object type model_workflow.py
model.sandbox_ops.object_types_ops.create create multiple object types
model.sandbox_ops.object_types_ops.update update a object type
model.sandbox_ops.object_types_ops.delete delete a sandbox object type

3. Requirements

  • Python 2.7 or Python 3.6
  • libraries: requests, six

4. Installation & Configuration

From PyPI:

$ pip install smartobjects

Alternatively, if you want to use the client from a data science perspective you can install with pandas extra (see Search Services:

$ pip install smartobjects[pandas]

From the sources:

$ git clone https://github.com/mnubo/smartobjects-python-client.git
$ cd smartobjects-python-client
$ python setup.py install

5. Usage

Initialize the MnuboClient

from smartobjects import SmartObjectsClient
from smartobjects import Environments, ExponentialBackoffConfig

client = SmartObjectsClient('<CLIENT_ID>', '<CLIENT_SECRET>', Environments.Production)
client_with_backoff = SmartObjectsClient('<CLIENT_ID>', '<CLIENT_SECRET>', Environments.Production, backoff_config=ExponentialBackoffConfig())

The environment argument can be Environments.Sandbox or Environments.Production or one of your custom urls to access the mnubo platform.

You can also initialize the client with a static token but this is not recommended for production because the token will eventually expires:

from smartobjects import SmartObjectsClient
from smartobjects import Environments, ExponentialBackoffConfig

client = SmartObjectsClient.withToken('<YOUR_TOKEN>', Environments.Sandbox)
client_with_backoff = SmartObjectsClient.withToken('<YOUR_TOKEN>', Environments.Sandbox, backoff_config=ExponentialBackoffConfig())

Optional arguments:

  • compression_enabled: if True, data sent to the platform is compressed using gzip format. Default: True
  • backoff_config: if given, requests resulting in 503 will be retried. Default: None
  • token_override: if given, the OAuth2 dance is avoid and this token is always used. Default: None

Note: to use exponential backoff retries feature, you must pip install tenacity (4.2.0+)

Use the Owners service

To create owners on the mnubo SmartObjects platform, please refer to the data modeling guide to format correctly the owner's data structure.

Create an Owner

client.owners.create({
    "username": "sheldon.cooper@caltech.edu",
    "x_password": "****************",
    "zip_code": "91125"
})

Mandatory properties: username, x_password

Claim or unclaim a Smart Object for an Owner

client.owners.claim('sheldon.cooper@caltech.edu', 'fermat1901')
# if you want to override some values
client.owners.claim('sheldon.cooper@caltech.edu', 'fermat1901', {
    "x_timestamp": 2015-02-01T05:00:00.000Z"
})


client.owners.unclaim('sheldon.cooper@caltech.edu', 'fermat1901')
# if you want to override some values
client.owners.unclaim('sheldon.cooper@caltech.edu', 'fermat1901', {
    "x_timestamp": 2015-02-01T05:00:00.000Z"
})

As a batch:

client.owners.batch_claim([
    ('sheldon.cooper@caltech.edu', 'fermat1901'),
    ('leonard.hofstadter@caltech.edu', 'ramanujan1887')
])

Update an Owner

client.owners.update('sheldon.cooper@caltech.edu', {
    "zip_code": "94305",    # update of an existing property
    "service_type": "phd"   # creation of a new property
})

Create or update owners in batch

results = client.owners.create_update([
    {"username": "sheldon.cooper@caltech.edu", "service_type": "prof"},
    {"username": "leonard.hofstadter@caltech.edu", "x_password": "*******"}
])

Mandatory properties: x_username_id (all owners), x_x_password_type (new owners)

Returns a list of Result with the completion status of each operation (and reason of failure if any).

Delete an Owner

client.owners.delete('sheldon.cooper@caltech.edu')

Check if an owner exists

>>> client.owners.owner_exists('sheldon.cooper@caltech.edu')
True

>>> client.owners.owners_exist(['sheldon.cooper@caltech.edu', 'hwolowitz.phd@caltech.edu'])
{'sheldon.cooper@caltech.edu': True, 'hwolowitz.phd@caltech.edu': False}

Use the Smart Objects Service

To create smart objects on the mnubo SmartObjects platform, please refer to the data modeling guide to format correctly the smart object's data structure.

Create a Smart Object

client.objects.create({
    "x_device_id": "fermat1901",
    "x_object_type": "calculator",
    "precision": "infinite"
})

Mandatory properties: x_device_id, x_object_type

Update a Smart Object

client.objects.update("fermat1901", {
    "is_valid": True
})

Create or update objects in batch

If an object doesn't exist, it will be created, otherwise it will be updated.

client.objects.create_update([
    {"x_device_id": "fermat1901", "is_valid": False},
    {"x_device_id": "ramanujan1887", "x_object_type": "pie"}
])

Mandatory properties: x_device_id (all objects), x_object_type (new objects)

Returns a list of Result objects with the completion status of each operation (and reason of failure if any).

Delete a Smart Object

client.objects.delete("fermat1901")

Check if an object exists

>>> client.objects.object_exists('fermat1901')
True

>>> client.objects.objects_exist(['fermat1901', 'teleporter'])
{'fermat1901': True, 'teleporter': False}

Use the Event Services

To send events to the mnubo SmartObjects platform, please refer to the data modeling guide to format correctly the event's data structure.

Send an Event

results = client.events.send([
    {"x_object": {"x_device_id": "fermat1901"}, "status": "running"},
    {"x_object": {"x_device_id": "ramanujan1887"}, "ratio": 3.1415}
])

Optional arguments:

  • must_exist: if True, an event referring an unknown object will be rejected (default to False)
  • report_results: if True, a list of EventResult objects will be returned with the status of each operation. If False, nothing will be returned when all events are successfully ingested, but a ValueError exception will be thrown if at least one fail. Default to True.

Send an event tagged with a device

This method allows sending multiple events for a given device without the need of setting the target in the payload.

results = client.events.send_from_device("ramanujan1887", [
    {"ratio": 3.1414},
    {"ratio": 3.1413}
])

Optional arguments:

  • report_results: if True, a list of EventResult objects will be returned with the status of each operation. If False, nothing will be returned when all events are successfully ingested, but a ValueError exception will be thrown if at least one fail. Default to True.

Check if an event already exists

>>> client.events.event_exists(UUID("1ff58794-f0da-4738-8444-68a592de6746"))
True

>>> client.events.events_exist([UUID("1ff58794-f0da-4738-8444-68a592de6746"), uuid.uuid4()])
{UUID("1ff58794-f0da-4738-8444-68a592de6746"): True, UUID("e399afda-3c8b-4a6d-bf9c-c51b846c214d"): False}

Use the Search Services

To send search queries to the mnubo SmartObjects platform, please refer to the Search API documentation to format your queries correctly.

Search Query

resultset = client.search.search({
    "from": "owner",
    "limit": 100,
    "select": [
        {"value": "username"}
    ]
})

This method returns a ResultSet containing the result of the search (columns and rows).

>>> "Got {} results!".format(len(resultset))
Got 2 results!
>>> [row.get("username") for row in resultset]
["sheldon.cooper@caltech.edu", "leonard.hofstadter@caltech.edu"]

Optionally, if you are using the SDK with pandas, you can use the propery df of the resultset. It will return a DataFrame version of the results, with datetime columns converted to a datetime structure.

resultset = client.search.search({
    "from": "event",
    "select": [
        {"count": "*"}
    ],
    "groupByTime": {
        "interval": "year",
        "field": "x_timestamp"
    }
})

resultset.df
#                   year  COUNT(*)
# 0 2017-01-01 05:00:00      1232

Validate a search query

For complex queries, it is recommended to use this feature to reduce errors.

validation_result = client.search.validate_query({
    "invalid": "owner",
    "limit": 100,
    "select": [
        {"value": "username"}
    ]
})

This method returns a QueryValidationResult object with the status of the validation and list of errors if any:

>>> validation_result.is_valid
False
>>> validation_result.validation_errors
["a query must have a 'from' field"]

Retrieve namespace datasets

This method allows to retrieve the different datasets available for querying. Result is a map of DataSet objects indexed by the dataset name (owner, object, event, session).

>>> datasets = client.search.get_datasets()
>>> [event.key for event in datasets['event'].fields]
["event_id", "x_object.x_device_id", "timestamp", ...]

Use the Model Service

Retrieve the model

To retrieve the model as it is currently in the zone you are working (sandbox or production), you can use the ModelService:

model = client.model.export()
print(len(model.eventTypes)) # outputs: 2

Get Timeseries

tss = client.model.get_timeseries()
print("Number of Timeseries: {}", len(tss))

Get Object Attributes

objs = client.model.get_object_attributes()
print("Number of Object Attributes: {}", len(objs))

Get Owner Attributes

owners = client.model.get_owner_attributes()
print("Number of Owner Attributes: {}", len(owners))

Get Event Types

ets = client.model.get_event_types()
print("Number of Event Types: {}", len(ets))

Get Object Types

ots = client.model.get_object_types()
print("Number of Object Types: {}", len(ots))

Sandbox only operations

Create multiple event types
client.model.sandbox_ops.event_types_ops.create([{
    'key': 'key',
    'origin': 'scheduled',
    'description': '',
    'timeseriesKeys': []
}])
Create one event type
client.model.sandbox_ops.event_types_ops.createOne({
    'key': 'key',
    'origin': 'scheduled',
    'description': '',
    'timeseriesKeys': []
})
Update an event type
client.model.sandbox_ops.event_types_ops.update(key, {
    'key': 'key',
    'origin': 'unscheduled',
    'description': 'new description',
    'timeseriesKeys': []
})
Delete an event type
client.model.sandbox_ops.event_types_ops.delete(key)
Create multiple object types
client.model.sandbox_ops.object_types_ops.create([{
    'key': 'key',
    'description': '',
    'objectAttributesKeys': []
}])
Create one object type
client.model.sandbox_ops.object_types_ops.createOne({
    'key': 'key',
    'description': '',
    'objectAttributesKeys': []
})
Update an object type
client.model.sandbox_ops.object_types_ops.update(key, {
    'key': 'key',
    'description': 'new description',
    'timeseriesKeys': []
})
Delete an object type
client.model.sandbox_ops.object_types_ops.delete(key)
Create multiple timeseries
client.model.sandbox_ops.timeseries_ops.create([{
    'key': 'ts_key',
    'displayName': '',
    'description': '',
    'type': {
        'highLevelType': 'TEXT'
    },
    'eventTypeKeys': [key]
}])
Create one timeseries
client.model.sandbox_ops.timeseries_ops.createOne({
    'key': 'ts_key',
    'displayName': '',
    'description': '',
    'type': {
        'highLevelType': 'TEXT'
    },
    'eventTypeKeys': [key]
})
Update a timeseries
client.model.sandbox_ops.timeseries_ops.update(
    'ts_key',
    {
        'displayName': 'new desc',
        'description': 'new dp',
    }
)
Deploy a timeseries in production
client.model.sandbox_ops.timeseries_ops.deploy('ts_key')
Create multiple object attributes
client.model.sandbox_ops.object_attributes_ops.create([{
    'key': 'obj_key',
    'displayName': '',
    'description': '',
    'type': {
        'containerType': 'none',
        'highLevelType': 'AREA'
    },
    'objectTypeKeys': [key]
}])
Create one object attribute
client.model.sandbox_ops.object_attributes_ops.createOne({
    'key': 'obj_key',
    'displayName': '',
    'description': '',
    'type': {
        'containerType': 'none',
        'highLevelType': 'AREA'
    },
    'objectTypeKeys': [key]
})
Update one object attribute
client.model.sandbox_ops.object_attributes_ops.update(
    'obj_key',
    {
        'displayName': 'new desc',
        'description': 'new dp',
    }
)
Deploy an object attribute in production
client.model.sandbox_ops.object_attributes_ops.deploy('obj_key')
Create multiple owner attributes
client.model.sandbox_ops.owner_attributes_ops.create([OwnerAttribute({
    'key': 'owner_key',
    'displayName': '',
    'description': '',
    'type': {
        'containerType': 'none',
        'highLevelType': 'FLOAT'
    }
})])
Create one owner attribute
client.model.sandbox_ops.owner_attributes_ops.createOne(OwnerAttribute({
    'key': 'owner_key',
    'displayName': '',
    'description': '',
    'type': {
        'containerType': 'none',
        'highLevelType': 'FLOAT'
    }
}))
Update one owner attribute
client.model.sandbox_ops.owner_attributes_ops.update(
    'owner_key',
    {
        'displayName': 'new desc',
        'description': 'new dp',
    }
)
Deploy an owner attribute in production
client.model.sandbox_ops.owner_attributes_ops.deploy('owner_key')

6. Need help?

Reach us at support@mnubo.com