Sequence CRUD

The Big Block Server supports sequences of steps.  The following Python script provides an example of how to Create, Read, Update, or Delete Sequences using the REST API.

###################################################################################################
#                                                                                                 #
# SEQUENCING                                                                                      #
#                                                                                                 #
# This Python script documents the Voodoo Robotics Sequencing feature using Python functions      #
# to communicate with the Voodoo Robotics REST API set.                                           #
#                                                                                                 #
###################################################################################################

# We use the Python requests library
import requests

# For pretty printing Python dictionaries and arrays in this demo, we use the json.dumps function
import json

# To start we have to log into the Big Block server.  In Python we do this by creating a session object.
session = requests.session()

# The following base endpoint should be modified to point to your server.  In this example, we use the 
# multi-tenant server on AWS.
url = 'https://www.voodoodevices.com/api/'

# Now with the session object we call the post method. Notice for login that the endpoint in this example is
# https://www.voodoodevices.com/api/user/login/  The result of the POST call goes into the variable 'x'.
# x = session.post(url+"user/login/",json={'username': 'yourusername','password':'yourpassword'})
x = session.post(url+"user/login/",json={'username': 'yourusername','password':'yourpassword'})

# If you want to see the output of the post (perhaps your login went awry), try 
# print(x.text)
# print(x.status_code)
# print(x.headers)

# Assuming the login went okay, we parse the resulting JSON.  The variable 'z' will contain a Python 
# dictionary. Python dictionaries are just like a hash map.
z = x.json()

# Now this is critically important: All the functions that we define below are going to use the 
# same session object that we created and logged in with. That session object holds a cookie in memory with 
# the Big Block sessionid or 'SESSID'. That cookie is sufficient for GET requests, but in order to make POST 
# or PUT requests, we need to add an additional couple of headers. Let's define the variable 'head' to hold 
# those two extra headers. 
head = {'referer': url,'x-csrf-token': z['token'],}
# Notice how we took the 'token' out of the 'z' that was passed back to us.  This token needs to be added to
# the header and labelled 'x-csrf-token'.  For more information about this special token and why it's needed,
# check out https://seclab.stanford.edu/websec/csrf/csrf.pdf  Basically, we cannot trust that cookies are kept 
# secret. Having the extra header prevents session riding attacks. 
# See https://en.wikipedia.org/wiki/Cross-site_request_forgery

# Now that we're logged in, we can define some functions
def allSequences():
    """All Sequences
    Get a list of all the Sequences.
    This returns ALL Sequences, unstarted, started, and completed.
    If the Sequence has a start time but not a complete time, then the Sequence is in progress,
    meaning that some steps have not yet executed.

    Returns:
        An array of sequences and their attributes (sequence nonce, start_time, and complete_time).
        Steps are not included.
    """
    x=session.get(
        url+"sequence/", # If you do not specify a Sequence ID, you get a list of all sequences
        headers = head,
        )
    return x.json()

# print("existing sequences")
# sequenceList = allSequences()
# print(json.dumps(sequenceList, indent=4))

def createSequence(seqID):
    """Create Sequence

    Launching the sequence means the steps execute in order, using the 'order' field.
    In this example, order 1 comes first.  Only after acknowledging step 1, the next two
    steps fire in tandem, because they have the same 'order' values. After the picker
    acknowledges both of those steps, the fourth step fires.
    Each step specifies an exising device, or a location name. If the step specifies a           
    location, the system finds the first device associated with that location using super-string 
    matching, i.e. only a portion of the location needs to be specified.  If two locations match,
    the result is unpredictable, since the first device with a match will be used.                                                                                    
    Just as with regular commands, each step can have five lines (line 1-5).  The stepnonce, goes to 
    the feedback server, if specified on an acknowledgment (ACK) or timeout (NACK) on each device. 
    The sequencenonce is sent after the acknowledgment of the last step in the sequence.        

    Args:
        seqID (str): The text name of the Sequence.
    """
    session.post(
        url+"sequence/",
        headers = head,
        json =  {
            "sequenceid": seqID,
            "sequencenonce": seqID + 'Order 314 Completed',
            "steps": [
                {"order":1, "device":"CAE96B:5DC841", "command":"flash", "line1":"Take 4", 
                 "line2":"of SKU 567-554", "line3":"\\icleft", "seconds":300},
                {"order":2, "location": "Warehouse Display", "command":"flash", "line1":"Betty", 
                 "line2":"PICK", "line3":"\\bcSKU 567-554", "line4":"\\qt36", 
                 "seconds":300, "color":"g"},
                {"order":2, "device": "D59094:AD433B", "command":"flash", "line1":"Betty", 
                 "line2":"PICK", "line3":"\\qrSKU 567-554", "line4":"\\qt36", 
                 "seconds":300, "color":"b"},
                {"order":4, "device": "D255D3:3A17E8", "command":"flash", "line1":"Pick", 
                 "line2":"\\bcSKU 567-554", "line3":"\\icleft", "line4":"\\qt4", "seconds":30, 
                 "stepnonce":"Item|4|completed", "sound":"15,c5,4"}
            ]
        } 
    )

# When launched using the web interface on Big Block, certain of the fields in each of the above steps 
# can be overridden. The fields that can be overridden are designated at the time of system installation.


# sequenceID = "Test_3" # Define the "Sequence ID" to provide a name for the Sequence. Each Sequence ID 
# should be unique. 

# createSequence(sequenceID)
# print("existing sequences plus Test_3")
# sequenceList = allSequences()
# print(json.dumps(sequenceList, indent=4))

def readSequence(seqID):
    """Read Sequence
    This function returns the specified sequence (including Steps)

    Args:
        seqID (str): The text name of the Sequence.

    Returns:
        The full sequence including and its steps.
    """
    x = session.get(
        url+"sequence/"+ str(seqID) +"/",
        headers = head,
    )
    return x.json()

# print(sequenceID)
# print(json.dumps(readSequence(sequenceID), indent=4))


def updateSequence(seqID):
    """Update Sequence
    The update function replaces the content of the existing sequence. 
    This example replaces the sequence we created above with one that only has steps 5 and 6.

    Note that this is a "put" and not a "post" in this function.

    Args:
        seqID (str): The text name of the Sequence.
    """
    x = session.put(
        url+"sequence/"+str(seqID)+"/",
        headers = head,
        json = {
            "sequenceid": seqID, 
            "sequencenonce": "Order 314: Updated order completed",
            "steps": [
                {"order":5, "location": "Warehouse Display", "command":"flash", "line1":"Betty", 
                 "line2":"PICK", "line3":"\\bcSKU 567-554", "line4":"\\qt36", 
                 "seconds":300, "color":"g"},
                {"order":6, "device": "D255D3:3A17E8", "command":"flash", "seconds":10, 
                 "stepnonce":"Item|4|completed", "sound":"15,c5,4" }
            ]
        }  
    )

# updateSequence(sequenceID)
# print("Update so that the sequence contains only steps 5 and 6")
# print(json.dumps(readSequence(sequenceID), indent=4))

def deleteSequence(seqID):
    """Delete Sequence
    Deletes the specific sequence.

    Args:
        seqID (str): The Sequence to delete.
    """
    session.delete(
        url+"sequence/"+ str(seqID) +"/",
        headers = head,
    )


def launchSequence(seqID):
    """Launches the specific sequence.
    This function will launch a sequence or relaunch a stalled sequence.
    (Sequences stall when one of the steps times out.)
    In the Big Block web interface, a sequence can be launched by a picker or manager account.
    
    Args:
        seqID (str): The Sequence to start.
    """
    session.get(
        url+"launchsequence/"+ str(seqID) +"/",
        headers = head,
    )

# launchSequence(sequenceID)

© Copyright 2024 Voodoo Robotics. All Rights Reserved. Patents Pending. Voodoo Robotics, Voodoo Devices, Big Block Server, and Turbo names and logos are all trademarks of Voodoo Robotics.