Skip to content

Python Example

Below is a simple example of an integration of the ColonyCam Client API in Python v3. The example runs the following actions.

  • call_drawer_endpoint(INITIALISE_ENDPOINT) - Initialises the ColonyCam
  • call_drawer_endpoint(OPEN_DRAWER_ENDPOINT) - Opens the ColonyCam drawer
  • call_drawer_endpoint(CLOSE_DRAWER_ENDPOINT) - Closes the ColonyCam drawer
  • take_image(IMAGE_PATH) - Takes an image

To test this example you should follow the following steps

  • Ensure python is installed on your machine

Can download Python from the official website. All of the libraries listed in the code are included as part of the Python standard library

You can run the code in Linux/MacOSX by opening a terminal and navigating to the directory the python file is in and supplying the <server_address:port> as an argument. (You may have to change the hashbang string at the top of the file to match your current installed version of python)

python3 path/to/PythonAPIClientExample.py 192.168.1.0:8080

On Windows you can open a command prompt and either navigate to the directory the python file is in, or supply the path and can use the slightly more generic binary file executable python

python path\to\PythonAPIClientExample.py 192.168.1.0:8080

The image will be saved to the user's home directory as the filename newimg.png

The API example uses two functions, one to call the drawer endpoints, which return json, and another to call the image endpoint which returns a Byte Array. Here are the libraries used, and the endpoint call functions.

import ssl
import os
import sys
import json
import urllib.error
from pathlib import Path
from urllib import request

unverified_context = ssl._create_unverified_context()

def call_drawer_endpoint(drawer_endpoint):
    try:
        response = request.urlopen(drawer_endpoint, context=unverified_context)
        status_code = response.getcode()
        content = response.read().decode('utf-8')

        if (status_code == 200):
            print("Success: ")
            try:
                content_json = json.loads(content)
                print(json.dumps(content_json, indent=2))
            except json.JSONDecodeError:
                print(content)
        else:
            print(f"Unexpected status code: {status_code}")
            print(content)

        return status_code, content

    except urllib.error.HTTPError as e:
        print(f"HTTP Error {e.code}: {e.reason}")
        error_content = e.read().decode('utf-8')
        print(f"Error content: {error_content}")
        return e.code, error_content

    except urllib.error.URLError as e:
        print(f"URL Error: {e.reason}")
        return None, str(e.reason)

    except Exception as e:
        print(f"An unexpected error occurred: {str(e)}")
        return None, str(e)

def take_image(img_path):
    try:
        response = request.urlopen(IMAGE_ENDPOINT, context=unverified_context)
        status_code = response.getcode()
        response_content = response.read()

        if (status_code == 200):
            print("Success, Image taken:")
            try:
                open(img_path, 'wb').write(response_content)
            except FileNotFoundError:
                print(f"Directory not found: {os.path.dirname(img_path)}")
            except PermissionError:
                print(f"Permission denied: Cannot write to {img_path}")
            except IsADirectoryError:
                print(f"Cannot write to a directory: {img_path}")
            except OSError as e:
                print(f"OS error occurred: {e}")
            except TypeError:
                print("Invalid data type: response_content must be bytes-like object")
            except Exception as e:
                print(f"An unexpected error occured: {e}")
        else:
            print(f"Unexpected status code: {status_code} ")
            content = response_content.decode('utf-8')
            print(content)

        return status_code

    except urllib.error.HTTPError as e:
        print(f"HTTP Error {e.code}: {e.reson}")
        error_content = e.read().decode('utf-8')
        print(f"Error content: {error_content}")
        return e.code, error_content

    except urllib.error.URLError as e:
        print(f"URL Error: {e.reason}")
        return None, str(e.reason)

    except Exception as e:
        print(f"An unepected error occurred: {str(e)}")
        return None, str(e)

    return status_code

The endpoints (and image path) are then provided as string arguments in the form

SERVER_ADDRESS = sys.argv[1] if len(sys.argv) > 1 else "0.0.0.0:8080"
OPEN_DRAWER_ENDPOINT = f"http://{SERVER_ADDRESS}/v1/open-drawer"
CLOSE_DRAWER_ENDPOINT = f"http://{SERVER_ADDRESS}/v1/close-drawer"
INITIALISE_ENDPOINT = f"http://{SERVER_ADDRESS}/v1/initialise"
IMAGE_ENDPOINT = f"http://{SERVER_ADDRESS}/v1/image"
IMAGE_PATH = f"{Path.home()}/newimage.png"

You can then call the defined functions with string arguments in the main body of the Python code.