THE EASIEST

Pick-to-Light REST Integration

Pick to Light example device

Simple!  The way it should be.

Two different APIs

Voodoo Robotics supports two different APIs for interacting with Pick-to-Light devices.

Integration between your warehouse management system (WMS) or Enterprise Resource Management Solution (ERP) is easy.

  • Simple. The easiest pick-to-light integration is the simple query string with a GET request. We suggest using this for initial evaluation. This does not use REST principles.
  • Advanced. For more powerful interfaces, consider using our REST API. It is slightly more complicated, but really worth the trouble.

This is a playlist of REST API tutorials on our Voodoo Robotics YouTube Channel

  • Get a list of all devices in your account.  Use a GET request on the endpoint https://www.voodoodevices.com/api/device/.  As with most REST servers, you can use XML or JSON in your request.  See the examples below.

  • Inspect Request

    Once you have a particular DeviceID, you can get more information about that device (voltage, uptime, etc.).  Use a GET request on the endpoint https://www.voodoodevices.com/api/device/FFFFFF:EEEEEE/.  As above, you can use XML or JSON in your request.

  • Update Request

    You can also update the message on a Device.  Use a POST request on the endpoint https://www.voodoodevices.com/api/device/FFFFFF:EEEEEE/.  You can submit your data as application/xml or application/json.  Notice that POST and PUT are equivalent in our REST API since there is no object creation mechanism.

  • Update Multiple

    You can also update multiple Devices in one API call.  Use a POST request on the endpoint https://www.voodoodevices.com/api/devices/.  (Note the plural ‘devices’.)  You can submit your data as application/xml or application/json.  This saves time and resources by consolidating API calls.  See the example below.

  • Inspect Turbos

    In a similar way to the device endpoint, you can use the turbo endpoint to get information about your Turbos.  Use a GET request on the endpoint https://www.voodoodevices.com/api/turbo/, or https://www.voodoodevices.com/api/turbo/SERIALNO/.

The examples on this page show you how to really leverage the power of REST with our modern Cloud Display Devices.  You can write your code in any language you choose.  We have chosen Python for demonstration purposes because it is fairly easy for any programmer to read Python and understand the critical steps.

Be sure to read the comments around the code.  They can be very useful, particularly if you do not know Python.  If you prefer PHP, please go to the REST API using PHP page.

Most Simple Example (Python)

In just five lines of Python code, you can send a simple command to a device.

import requests,json
session = requests.Session()
url = "https://www.voodoodevices.com/api/"
x = session.post(url+"user/login/",json={'username': 'yourusername',
    'password':'yourpassword'})
z = json.loads(x.text)
session.post(
    url+"device/E8D008:619874/",
    headers = {'referer': url,'x-csrf-token': z['token'],},
    json={'command':'flash','line1':'Hello','line2':'There'},
)

#That was just FIVE LINES of CODE (plus a variable assignment)

#Here's a function and a function call
def simplePickCommand(deviceID,line1,line2):
    session.post(
        url+"device/"+deviceID+"/",
        headers = {'referer': url,'x-csrf-token': z['token'],},
        json={'command':'flash','line1':line1,'line2':line2},
    )

#now let's call the function
simplePickCommand('E8D008:619874','Ben','Take 5')
simplePickCommand('E476EA:EA3329','Fred Put','Red Shirts Here')

Step by Step (in Python)

Let’s walk through it together…

###################################################################################################
#                                                                                                 #
# Function Overview for Cloud Display Devices in Python.                                          #
#                                                                                                 #
# This Python script walks through use of the REST API for Cloud Display Devices.                 #
#                                                                                                 #
###################################################################################################

# 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'})

# 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 session 
# object 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 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. We need to add this token 
# the header and labelled 'x-csrf-token'. For more information about this special token and why it 
# is required, check out https://seclab.stanford.edu/websec/csrf/csrf.pdf  
# Basically, we cannot trust that cookies remain 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 getDeviceInfo(deviceID):
    """Get Device Info
    This function retrieves all available Cloud Display Device attributes from Big Block.

    Args:
        deviceID (str): A unique alphanumeric string that identifies the specific Cloud Display Device. 

    Returns:
        A dictionary of attributes for the specific Cloud Display Device.
    """
    x = session.get(url+"device/"+deviceID+"/",headers = head)
    return x.json()

# This is how you would use the getDeviceInfo function:

# deviceID = 'D4E825:8B665D'
# parsed_json = getDeviceInfo(deviceID)
# input("Press Enter to see all attibutes that the Cloud Display Device Stores")
# print(json.dumps(parsed_json, indent=4))

# To access some individual attributes:
# print("Last Reported Voltage: ", parsed_json["lastvoltage"])
# print("Location: ", parsed_json["locationoverride"])
# or, by using variables:
# attributeLabel = "Voltage: "
# attribute = "lastvoltage"
# print(attributeLabel, parsed_json[attribute])

# The code works if you already know the deviceID. But what if you don't? Here's how you get a list
# of all your deviceIDs.

def getDeviceArray():
    """Get Device Array

    A function that returns a list of all Device IDs in Big Block.

    Returns:
        A list of devices IDs.
    """
    x=session.get(
        url+"device/", #Because there is no specific Device ID, the function resturns a list of them.
        headers = head,
        )
    return x.json()

# Here's how you'd use this function:

# deviceList = getDeviceArray()
# input("Press Enter to see a list of all Cloud Display Devices")
# print(json.dumps(deviceList, indent=4))

def getDeviceArrayWithSubstring(locationSubstring):
    """Get Device Array

    A function that returns a list of all Device IDs in Big Block.

    Returns:
        A list of devices IDs.
    """
    x=session.get(
        url+"device/"+locationSubstring+"/", # Because there is a substring here, the array will return 
        # all of the devices with a location that contains that substring.
        headers = head,
        )
    return x.json()


# Here's a function that helps light up a device with a message
def messageDevice(deviceID, command = 'flash', line1 = '', line2 = '', line3 = '', 
                                line4 = '', line5 = '', time = 10, sound = '15,c5,4', color = 'r'):
    """Message Device

    This function illustrates how to send a command to a device to force it to light up. 

    Args:
        deviceID (str): A unique alphanumeric string that identifies the specific Cloud Display Device. 
        command (str): Specifies the light behavior for the device.
        * If the command is 'flash', the light flashes.
        * If the command is 'display', the light is solid. (We recommend flash, as it uses less power.)
        line1 (str): Line 1 of the message.
        line2 (str): Line 2 of the message.
        line3 (str): Line 3 of the message.
        line4 (str): Line 4 of the message.
        line5 (str): Line 5 of the message.
        * lines 1-5 must be less than 26 characters each, including any prefix.
        * The prefix is used for encoded elements, such as barcodes, QRcodes, icons or arrows.
        * See https://voodoorobotics.com/line-encodings/
        time (int): The amount of time that the device lights up before timing out. Defaults to 10.
        sound (str): The sound that the device makes when lighting up. Defaults to '15,c5,4'.
        * Sound strings are just the tempo followed by a series of notes. See our Section 6 of our page
          at https://voodoorobotics.com/constructing-a-url/ for some examples.
        * Using long sounds consumes batteries quickly, so try to use simple sounds like a simple 
          beep ('15,c5,4').
        * See our battery estimator at https://voodoorobotics.com/pick-light-batteries/
        color (str): The color of the LED that lights up for the command. Defaults to 'r'. 
          Allowable values are Red ('r'), Blue ('b'), Green ('g'), Magenta ('m' or 'rb'), 
          Cyan ('c' or 'bg'), or  Yellow ('y' or 'rg').
    """

    session.post(
        url+"device/"+deviceID+"/",
        headers = head,
        json = {
            'api':'2.0',
            'command': command,
            'line1': line1,
            'line2': line2,
            'line3': line3,
            'line4': line4,
            'line5': line5,
            'seconds': time,
            'sound': sound,
            'color': color,
        },
    )


 # Our feedback protocol uses nonces. See https://voodoorobotics.com/closed-loop-system/.
 # Here's a similar function that sets the nonce.
def messageDeviceWithNonce(deviceID, line1, nonce, time = 10, sound = '15,c5,4', color = 'r'):
    """Message Device with Nonce

    Args:
        deviceID (str): A unique alphanumeric string that identifies the specific Cloud Display Device.
        line1 (str): Line 1 of the message. (This example only has one line, since the objective is to 
           demonstrate the nonce.)
        nonce (str): A string or unique number that serves as feedback when acknowledging the message.
        time (int): The amount of time that the device lights up before timing out. Defaults to 10.
        sound (str): The sound that the device makes when lighting up. Defaults to '15,c5,4'.
        color (str): The color of the LED that lights up for the command. Defaults to 'r'. 
          Allowable values are Red ('r'), Blue ('b'), Green ('g'), Magenta ('m' or 'rb'), 
          Cyan ('c' or 'bg'), or  Yellow ('y' or 'rg').

    """
    
    session.post(
        url+"device/"+deviceID+"/",
        headers = head,
        json = {
            'api':'2.0',
            'command': 'flash',
            'line1': line1,
            'nonce': nonce, # Nonce added for feedback
            'seconds': time,
            'sound': sound,
            'color': color,
        },
    )

# You might call this function like this:
# messageDeviceWithNonce(deviceID,'Line1', 'Nonce123', time = 10, sound = '15,c5,4', color = 'r')

# Beyond feedback, setting a nonce allows you to do this:
def killMessage(deviceID,nonce):
    """Kill Message
    Terminate a currently pending command.
    To use kill function, you must reference the command both by the device ID and the nonce 
    you originally used when you sent the command.

    Args:
        deviceID (str): A unique alphanumeric string that identifies the Cloud Display Device.
        nonce (str): A string or unique number that identifies the specific command to kill.
    """
    session.post(
        url+"device/"+deviceID+"/",
        headers = head,
        json = {
            'api':'2.0',
            'command': 'kill',
            'nonce': nonce,
        },
    )
 
 # You can also remove ALL pending commands from a device with a reset.
def resetDevice(deviceID):
    """Reset Device
    Resetting a device removes all commands in the device's queue (including overlapped commands).

    Args:
    deviceID (str): A unique alphanumeric string that identifies the specific Cloud Display Device.
    """
    session.post(
        url+"device/"+deviceID+"/",
        headers = head,
        json = {
            'api':'2.0',
            'command': 'reset',
        },
    )

# Another way to remove all pending commands is to completely reboot a device.
def rebootDevice(deviceID):
    """Reboot Device
    Rebooting a device is like power-cycling the device, i.e. replacing the batteries.
    It causes all pending commands to be lost.

    Args:
    deviceID (str): A unique alphanumeric string that identifies the specific Cloud Display Device.
    """
    
    session.post(
        url+"device/"+deviceID+"/",
        headers = head,
        json = {
            'api':'2.0',
            'command': 'reboot',
        },
    )


# Between commands, when the device is idle, it displays what we call 'static' text. You might think 
# of this as the 'default' display--what displayed when there is no command pending. Here's how you 
# would set the static text on a device.
def simpleStaticMessage(deviceID, statica, staticb, staticc, staticd, statice, timeout = 5, 
                        location_override = "", brightness = 50):
    """Simple Static Message

    Just like the lines in a command, static text lines statica through statice must be less than 26 characters, 
    including any prefix.

    You can use QR Codes, Barcodes, Icons, and a Quantity in a static messsage, using 'bc' for barcode, 'ic' for 
    icon, and 'qr' for a QR Code. For a list of possible options 
    see this discussion at https://voodoorobotics.com/line-encodings.
    Having a barcode and a QR code in close proximity might confuse some barcode scanners, 
    so you should NOT use both of them in the same display.
    To summarize, the syntax for the line prefixes is as follows (using an extra \ to escape the backslash 
    in Python):
    * QR Code: '\\qr' (limited to 23 characters of the encoded string, e.g., '\\qrtinyurl.com/mtkjyapu')
    * Standard 2 dimensional barcode: '\\bc' (limited to 23 characters of the encoded string,, 
      e.g., '\\bcSKU123-649'.
      The text for the barcode displays under the barcode)
    * Icon: '\\ic' (e.g., '\\ichazardI)
    * Quantity: '\\qt (e.g., '\\qt5' to display the quantity 5 in a box.) The quantity parameter in a box is only 
      available for quantities 0 to 99.
    * In Python, '\\qr' is a three character string!  Thus the limit of 23 characters in a QR code or barcode.
    You can also set the default display timeout with 'timeout'. Set a location override with 'location_override' 
    and brightness with 'brightness' (a value between 0 and 100).

    Args:
        deviceID (str): A unique alphanumeric string that identifies the specific Cloud Display Device.
        statica (str): Static message line a.
        staticb (str): Static message line b.
        staticc (str): Static message line c.
        staticd (str): Static message line d.
        statice (str): Static message line e
        timeout (int): Nothing to do with a command!  This is the number of seconds after which a device lights
        up to show location and area information before returning to static display. (Seldom used) 
        location_override (str): Separate area from location with a pipe, like 'MyArea|MyLocation'
        brightness (int): Sets the standard brightness for the light with a value from 0 to 100.
    """

    session.post(
        url+"device/"+deviceID+"/",
        headers = head,
        json = {
            'api':'2.0',
            'statica': statica,
            'staticb': staticb,
            'staticc': staticc,
            'staticd': staticd,
            'statice': statice,
            'timeout': timeout,
            'locationoverride': location_override,
            'brightness': brightness,
        },
    )

# Here's a more specific use case where we display quantities.
# Use '\qt' prefix for quantity as described on https://voodoorobotics.com/line-encodings
# In Python, we use a double escape like this '\\qt'. Since the number in the box is limited to 0-99, 
# "Quantity: " is used for cases where the quantiy exceeds 99.  
def messageDeviceQt(deviceID, line1, line2, line3, line4, qt, time = 10, sound = 'none', color = 'r'):
    """Message Device with Quantity
    This example illustrates the behavior of the quantity parameter.

    Args:
        deviceID (str): A unique alphanumeric string that identifies the specific Cloud Display Device. 
        command (str): Specifies the light behavior for the device.
        * If the command is 'flash', the light flashes.
        * If the command is 'display', the light is solid. (We recommend flash, as it uses less power.)
        line1 (str): Line 1 of the message.
        line2 (str): Line 2 of the message.
        line3 (str): Line 3 of the message.
        line4 (str): Line 4 of the message.
        qt (int): This message uses the numeric quantity to illustrate the behavior of the quantity parameter 
        time (int): Number of seconds before the command times out. Defaults to 10.
        sound (str): Tune to play through the speaker. Defaults to no sound.
        color (str): The color of the LED that lights up for the command. Defaults to 'r'. 
          Allowable values are Red ('r'), Blue ('b'), Green ('g'), Magenta ('m' or 'rb'), 
          Cyan ('c' or 'bg'), or  Yellow ('y' or 'rg').
    """
    if (qt <=99):
        qt = '\\qt'+str(qt)  # Quantities 99 or less can go in the box
    else:
        qt = "Quantity: "+str(qt) # Other quantites you have to spell out
        
    session.post(
        url+"device/"+deviceID+"/",
        headers = head,
        json = {
            'api':'2.0',
            'command': 'flash',
            'line1': line1,
            'line2': line2,
            'line3': line3,
            'line4': line4,
            'line5': qt,
            'seconds': time,
            'sound': sound,
            'color': color,
        },
    )
# You can call the above with
# messageDeviceQt(deviceID,'John','PICK', 'Red T-Shirts', '', qt=35, time = 10, sound = '15,c5,4', color = 'r')

# Just like we did with static messages, we can encode all sorts of things in commands
def messageDeviceFancy(deviceID, command, line1, line2, line3, line4, line5, time = 10, sound = '', color = 'r'):
    """Message Device Fancy

    You can use QR Codes, Barcodes, Icons, and a Quantity in a command message,  
    using 'bc' for barcode, 'ic' for icon, and 'qr' for a QR Code.
    For a list of possible icons see this discussion https://voodoorobotics.com/line-encodings.
    Having a barcode and a QR code in close proximity might confuse some barcode scanners, 
    so you should NOT use both of them in the same display.
    As mentioned, the syntax for the line prefixes is as follows (using an extra \ to escape the backslash 
    in Python):
    * QR Code: '\\qr' (limited to 23 characters of the encoded string, e.g., '\\qrtinyurl.com/mtkjyapu')
    * Standard 2 dimensional barcode: '\\bc' (limited to 23 characters of the encoded string,, 
      e.g., '\\bcSKU123-649'.
      The text for the barcode displays under the barcode)
    * Icon: '\\ic' (e.g., '\\ichazardI)
    * Quantity: '\\qt (e.g., '\\qt5' to display the quantity 5 in a box.) THIS EXAMPLE DOES NOT CONTROL THE
    QUANTITY PARAMETER BEHAVIOR. If the quantity is greater than 99, omit the prefix and use something like 
    "Quantity: " at the beginning of the string. See the example above.

    Args:
        deviceID (str): A unique alphanumeric string that identifies the specific Cloud Display Device. 
        command (str): Specifies the light behavior for the device.
        * If the command is 'flash', the light flashes.
        * If the command is 'display', the light is solid. (We recommend flash, as it uses less power.)
        line1 (str): Line 1 of the message.
        line2 (str): Line 2 of the message.
        line3 (str): Line 3 of the message.
        line4 (str): Line 4 of the message.
        line5 (str): Line 5 of the message.
        time (int): The amount of time that the device lights up before timing out. Defaults to 10.
        sound (str): The sound that the device makes when lighting up. Defaults to '15,c5,4'.
        color (str): The color of the LED that lights up for the command. Defaults to 'r'. 
          Allowable values are Red ('r'), Blue ('b'), Green ('g'), Magenta ('m' or 'rb'), 
          Cyan ('c' or 'bg'), or  Yellow ('y' or 'rg').
        
    """
    session.post(
        url+"device/"+deviceID+"/",
        headers = head,
        json = {
            'api':'2.0',
            'command': command,
            'line1': line1,
            'line2': line2,
            'line3': line3,
            'line4': line4,
            'line5': line5,
            'seconds': time,
            'sound': sound,
            'color': color,
        },
    )

# YOU SHOULD NEVER DO SOMETHING LIKE THIS
# Don't make the device light up and set static
# data at the same time. It can significantly slow down communications.
# session.post(
#     url+"device/"+deviceID+"/",
#     headers = head,
#     json =  {
#             'api':'2.0',
#             'command': 'flash',
#             'line1': line1,
#             'line2': line2,
#             'line3': line3,
#             'line4': line4,
#             'line5': line5,
#             'seconds': time,
#             'sound': sound,
#             'color': color,
#             'statica': statica,
#             'staticb': staticb,
#             'staticc': staticc,
#             'staticd': staticd,
#             'statice': statice
#      },
# )
# DO NOT DO THIS!!!


# Dealing with Turbos is similar to devices
# To get a list of Turbos on Big Block, try this:
def getArrayOfTurbos():
    """Get Array Of Turbos

    A function that returns a list of all Turbo IDs in Big Block.

    Returns:
        A list of Turbo IDs.
    """
    x = session.get(
        url+"turbo/", #Because there is no specific ID here, 
            # the function will return a list of all of them.
        headers = head,
    )
    return x.json()

# turboList = getArrayOfTurbos()
# input("Press Enter to see a list of all of your Turbos")
# print(json.dumps(turboList, indent=4))

# To get information on one specific Turbo, you can then do this:
def getTurboInfo(TurboID):
    """Get Turbo Info
    This function retrieves all available Turbo attributes from Big Block.

    Args:
        TurboID (str): A unique alphanumeric string that identifies the specific Turbo. 

    Returns:
        A dictionary of attributes for the specific Turbo.
    """
    x = session.get(
        url+"turbo/"+TurboID+"/",
        headers = head,
    )
    return x.json()

# turboInfo = getTurboInfo('1000000001bf8c0a')
# print(json.dumps(turboInfo, indent=4))

# OK, we saved the most useful for last:
# How about a single API call to light up multiple devices?
# Here we create an Array in JSON for several commands to several Devices
# Note that we use the 'devices' endpoint, not the 'device' endpoint

def helloTimesFive(deviceID1, deviceID2, deviceID3, deviceID4, deviceID5):
    """Hello Times Five
    This example function sends the same command to five devices with one API call.

    Args:
        deviceID1 (str): A unique alphanumeric string that identifies the first device. 
        deviceID2 (str): A unique alphanumeric string that identifies the second device. 
        deviceID3 (str): A unique alphanumeric string that identifies the third device. 
        deviceID4 (str): A unique alphanumeric string that identifies the fourth device. 
        deviceID5 (str): A unique alphanumeric string that identifies the fifth device. 

    """
    session.post(
        url+"devices/",
        headers = head,
        json = [
            {
                'api': '2.0',
                'deviceID': deviceID1,
                'command': 'flash',
                'line1': 'Hello',
                'line2': 'Howdy',
                'seconds': '10',
                'sound': '15,c5,4'
            },
            {
                'api': '2.0',
                'deviceID': deviceID2,
                'command': 'flash',
                'line1': 'Hello',
                'line2': 'Howdy',
                'seconds': '10',
                'sound': '15,c5,4'
            },
            {
                'api': '2.0',
                'deviceID': deviceID3,
                'command': 'flash',
                'line1': 'Hello',
                'line2': 'Howdy',
                'seconds': '10',
                'sound': '15,c5,4'
            },
            {
                'api': '2.0',
                'deviceID': deviceID4,
                'command': 'flash',
                'line1': 'Hello',
                'line2': 'Howdy',
                'seconds': '10',
                'sound': '15,c5,4'
            },
            {
                'api': '2.0',
                'deviceID': deviceID5,
                'command': 'flash',
                'line1': 'Hello',
                'line2': 'Howdy',
                'seconds': '10',
                'sound': '15,c5,4'
            },
        ]
    )
    
    
helloTimesFive('D4E825:8B665D', 'E8F297:F3F2F3', 'DB33A9:13897D', 'D255D3:3A17E8', 'D59094:AD433B')

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)

You May Also be Interested in:

Device Limitations

The REST API works for both our Modern Cloud Display Devices and our Classic devices.

Modern Cloud Display Devices devices support five lines both for commands and for static data.  As you can see in the code example we use line 1-5 and static a-e for these lines.  The device display will scale to fit the text that you send it, so if you have a five character string on only one line, it’ll be much larger than five 26-character lines.  Each line supports up to 26 characters.

Classic devices only support two lines of text.  The display is 16 characters wide, but you can send a maximum of 32 characters.  If you send more than 16 characters, the display will scroll back and forth, left to right.  Classic devices require a  bar delimiter ‘|’ to separate lines in a static call, and support both ‘static’ and ‘static2’.  Static is shown after a single button push, and static2 is shown after two button pushes.  Please contact us if you wish to replace your Classic devices with the new Modern devices.

Barcodes, QR Codes, and Icons

You can replace any command or static line of text on a Modern Cloud Display Device with a barcode, QR Code or icon.  As you can see in the example above, if you preface a line with ‘bc’ you will get a barcode.  If you preface a line with ‘qr’ you will get a QR Code.  And if you preface a line with ‘ic’ you will get an icon.  And, of course, you could do all three!

Since Modern devices have a limitation of 26 characters per line of text, barcodes and QR Codes are limited to 23 characters (three are used for the prefix).  Note that bitly links are 22 characters — so you can encode any URL on a device.

Modern devices also support two main types of icons: arrows and hazard signs.

Learn about the different encoding formats for icons.

© 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.