2. Advanced topics

2.1. Queries

The part attributes you added in the Tutorial let you select parts with simple queries like tray=1 and color=green. However, more complex queries are also possible using Lookups and Complex boolean queries.

Lookups

Queries allow lookups, for instance number__gt=1 selects all parts whose number is greater than 1. The exact lookups that are created depend on the attribute’s datatype:

lookup

datatypes

description

lt

NUMBER, DATETIME

less than, e.g. copies__lt=2 means at most one copy

gt

NUMBER, DATETIME

greater than, e.g. copies__gt=1 means at least two copies

istartswith

STRING

case-insensitive starts with

icontains

STRING

case-insensitive string containment test

contains

containment test, available when is_list=True

These filters are also available for use in the part endpoint, so you can for instance do:

response = api.part.get(tray=1, copies__lt=2)

Complex boolean queries

The query system mentioned above also allows complex compound queries using boolean operators:

operator

description

example

AND operator

copies__lt=2+tray=1


OR operator

copies__lt=2|tray=1

~

NOT operator

~tray=1

()

precedence copies__lt=2+(title__icontains=x|~tray=1)

2.2. Endpoint Operations

The AM-Vision API supports the following on all endpoints:

  • POST-ing individual items

  • GET-ting individual items as well as multiple via querystring filters

  • PUT-ting items in bulk

  • DELETE-ing items in bulk.

GET querystring filtering

All endpoints support a degree of filtering on resource fields. for example GET /api/batch/?title__icontains=demo. Supported filters per endpoint are listed in the API reference.

PUT update-or-create

for the PUT operation, a list of items is given. Each item is looked up by its id. If it already exists, the item is updated. If it does not exist, the item is created.

DELETE with filters

for the DELETE operation, the same set of filters can be used as for the GET endpoint. objects matching the filters will then be deleted in one call.

Examples

Here are some example bulk operations:

# some update-or-create examples
api.batch_category.put([
    {'id': 'by_tray', 'title': "View by tray"},
    {'id': 'by_method', 'title': "View by method"}
])
api.query.put([
    {'id': 'Green', 'query': 'dye=GREEN', 'sorting': True},
    {'id': 'Black', 'query': 'dye=BLACK', 'sorting': True},
])

# some deletion examples
# delete the black and green query
api.query.delete(id='Black,Green')
# delete all parts with more than two copies
api.part.delete(copies__gt=1)

2.3. Webhooks

The AM-Vision API can let you know when certain events occur by doing a POST to an endpoint in your own API. The following events are supported:

Event

Description

batch.start

The operator started scanning a batch

batch.end

The operator stopped scanning a batch

batch.reset

The operator reset a batch (dropped existing assignments)

batch.archive

The operator archived a batch

batch.unarchive

The operator unarchived a batch

batch.advance

The operator advanced a batch

scan.capture

A scan was taken by the AM-Vision

scan.reject

A scan was rejected by the operator

scan.assign

A scan was assigned to a part by the operator or AM-Vision

scan.unassign

A scan was unassigned from a part by the operator

You can subscribe to an event like this:

api.webhook.post({
    'event': 'scan.assign',
    'target': 'http://yourapi.com/on_scan_assigned/'
})

By default, the webhook POST will use the headers {"Content-Type": "application/json"}. But you can supply your own custom headers, for instance for authentication:

api.webhook.post({
    'event': 'scan.assign',
    'target': 'http://yourapi.com/on_scan_assigned/',
    'headers': {
        "Content-Type": "application/json",
        "Authorization": "Token XYZ"
    },
})

The content of the webhook is a serialization of the object that the event relates to, as well as a summary of the webhook subscription. Here’s an example of a batch.advance webhook (all batch-related webhooks look similar):

{
    'hook': {
        'id': 18,
        'event': 'batch.advance',
        'target': 'http://localhost:9000/test/'
    },
    'data': {
        'url': '/api/batch/999/',
        'created': '2022-01-19T12:05:16.655027+01:00',
        'modified': '2022-01-19T12:10:30.787503+01:00',
        'id': '999',
        'title': '999_Hp5_201114',
        'archived': false,
        'finalized': false,
        'category': None,
        'query': 'job_id=999&prev_step=Printing',
        'summary': {
            'assigned': 3,
            'reprinted': 0,
            'parts': 3,
            'unassigned_scans': 1,
            'needs_processing': false,
            'processing_status': 'READY',
            'processing_ratio': 1.0,
            'conflicted': 0,
            'currently_scanning': None
        },
        'has_output_assignments': true,
        'active_scan_session': '176719ae-29fb-4eb0-b41f-45f60e23f59d',
        'auto_delete': false,
        'attributes': {},
        'contents': { ... }
    }
}

Here’s an example of a scan.assign webhook (all scan-related webhooks look similar):

{
    'hook': {
        'event': 'scan.assign',
        'id': 8,
        'target': 'http://localhost:9000/hook/'
    },
    'data': {
        'url': '/api/scan/a208efd4-8e5a-11ec-a226-33350b016b70/',
        'created': '2022-02-15T13:27:25.838162+01:00',
        'modified': '2022-02-15T13:27:28.635543+01:00',
        'uuid': 'a208efd4-8e5a-11ec-a226-33350b016b70'
        'batch': {'id': 'demo_set_4', 'title': 'Demo set 4'},
        'output': {'id': '1'},
        'design_material': 'a1e76973c62d6c279aa7f50380fb713ac5cfb3b3_MTR_PRT_SLS_MAT_PA2200',
        'scan_session': '6bc50ccc-d65a-47cb-88dc-3a66f441b167',
        'assignment: {
            'assigned_copies': 1,
            'assignment': '30fbda68-7a2b-4b2d-a880-8ae7873792cc',
            'last_added_copies': 1,
            'total_copies': 1,
            'design_material': 'a1e76973c62d6c279aa7f50380fb713ac5cfb3b3_MTR_PRT_SLS_MAT_PA2200',
            'expected_copies': 1,
            'part_id': 'demo-SLS_nema17_25mm_10___1',
            'part_title': 'SLS_Nema17 25mm 10',
            'reprint': False,
            "reprint_comment":"None",
            "reprint_reasons":[]
        },
        'scan_urls': [
            '/data/scans/a208efd4-8e5a-11ec-a226-33350b016b70/scan_cam01.png',
            '/data/scans/a208efd4-8e5a-11ec-a226-33350b016b70/scan_cam02.png',
            '/data/scans/a208efd4-8e5a-11ec-a226-33350b016b70/scan_cam04.png',
            '/data/scans/a208efd4-8e5a-11ec-a226-33350b016b70/scan_cam03.png',
            '/data/scans/a208efd4-8e5a-11ec-a226-33350b016b70/scan_cam05.png'
        ],
        'scan_urls_full': [
            '/data/scans/a208efd4-8e5a-11ec-a226-33350b016b70/scan_cam01.full.png',
            '/data/scans/a208efd4-8e5a-11ec-a226-33350b016b70/scan_cam02.full.png',
            '/data/scans/a208efd4-8e5a-11ec-a226-33350b016b70/scan_cam04.full.png',
            '/data/scans/a208efd4-8e5a-11ec-a226-33350b016b70/scan_cam03.full.png',
            '/data/scans/a208efd4-8e5a-11ec-a226-33350b016b70/scan_cam05.full.png'
        ],
    },
}

The main event of interest is probably batch.advance. The idea is that the operator explicitly marks a batch as finished and your API can then update the batch and parts. For instance by:

  • Moving the parts to the next processing step, and re-uploading them to the AM-Vision for the second round sorting.

  • Automatically reprinting parts when scan assignments have the ‘reprint’ field set.

  • Forwarding the camera images from the AM-Vision to your customers.

You can unsubscribe from webhook notifications by DELETE-ing your subscription (using the id sent in every webhook POST):

# equivalent to DELETE /api/webhook/8
api.webhook(8).delete()

2.4. Notifications

You can send notifications to the UI for important events or errors. Here are some examples:

api.notification.post({'title': "Running importer"})
api.notification.post({
    'title': 'New batch uploaded',
    'body': 'batch title',
    'icon': 'fa fa-download',
    'auto_close': True
})
api.notification.post({
    'title': 'Error running importer',
    'body': 'error message',
    'icon': 'fa fa-exclamation-circle',
    'auto_close': False
})

2.5. BatchCategories

BatchCategories are a simple way to categorize your batches, displayed as tabs in the AM-Vision UI. BatchCategories contain the following fields:

id:

A unique slug id for the batch category

title:

Human-readable title for the batch category

This example creates a single tab to batch_category batches by Print tray:

batch_categories = [
    {
        "id": "by_tray",
        "title": "By Tray"
    },
]
api.batch_category.put(batch_categories)

You can then place batches in this tab by specifying the batch_category field in the batch definition.