Manage RICOH THETA From Office Network with Django

This example shows how to use and manage the RICOH THETA over your office network with Django.

You’ll learn how to use the RICOH THETA v2.1 API (OSC) API over your office network by putting the THETA V into client mode. To avoid the hassle of getting your staff to connect their phone or laptop to the THETA with Wi-Fi, we will use the THETA client mode network option to use your own office network to assign the camera an IP address automatically.

This project is intended for education of a few simple concepts only. It is not intended for production use. To keep the code simple and concise, there is only minimal error checking.

Getting the Code

Code for this project is available on GitHub.

Install Project Dependencies

I recommend you run Python in a virtualenv.

$ python3 -m pip install virtualenv

You can then create a virtualenv, start it, and install the Python requirements

$ virtualenv myvenv
$ source myvenv/bin/activate
$ pip install -r requirements.txt

Modify views.py for Your Camera Settings

You must change the three settings below for your specific camera.

################
# Change the settings below
################
# global constants specific to your THETA. Change for your camera.
THETA_IP = '192.168.2.101'
THETA_ID = 'THETAYL00105377'
THETA_PASSWORD = '00105377' # default password. may have been changed

How To Find IP Address of Camera

You can find the IP address with the script tools/find-theta.py. This uses zeroconf to find the THETA with network discovery.

Browsing services, press Ctrl-C to exit...

Service THETAYL00105377._osc._tcp.local. of type _osc._tcp.local. state changed: ServiceStateChange.Added
  Address: 192.168.2.101:80
  Weight: 0, priority: 0
  Server: THETAYL00105377.local.
  No properties

Once you find the IP address, you must modify the constant in views.py. In actual use, you can include discovery into your Django project or assign static IP addresses to the THETA hardware ID with your Wi-Fi router.

Run Django Server

(myvenv) $ python manage.py runserver

....
July 19, 2019 - 21:52:22
Django version 2.2.3, using settings 'shell.settings'
Starting development server at http://127.0.0.1:8000/
Quit the server with CONTROL-C.

Connect Browser

Open browser to localhost:8000

image

Clicking on one of the commands will show the HTTP response in the browser.

The image listing is basic right now.

image

You can preview the images directly on the camera before downloading the THETA images from the camera to your local system. The images are previewed in equirectangular.

Images are copied from the camera to your local machine. The original image remains on your camera. The interface is minimal.

image

Images are stored in project_home/media

image

Code Explanation

GET

The THETA API is run through an HTTP request using Python requests. To use client mode, you must also use Digest Authentication. The print statement is only for debugging purposes. You can delete it.

THETA_IP = '192.168.2.101'
THETA_ID = 'THETAYL00105377'
THETA_PASSWORD = '00105377'  # default password. may have been changed
THETA_URL = f'http://{THETA_IP}/osc/'


def info(request):
    url = f"{THETA_URL}info"
    resp = requests.get(url, auth=(HTTPDigestAuth(THETA_ID, THETA_PASSWORD)))
    data = resp.json()
    print(data)
    return render(request, 'commandhome.html', {'data': data})

POST

A simple post command is almost identical to the GET command. Note that the third parameter of render is a Python dictionary.

def state(request):
    url = f"{THETA_URL}state"
    resp = requests.post(url, auth=(HTTPDigestAuth(THETA_ID, THETA_PASSWORD)))
    data = resp.json()
    print(data)
    return render(request, 'commandhome.html', {'data': data})

Accessing data from HTML

In both examples, you can access the data value inside of your HTML with a simple for loop.

In commandhome.html

    <table>
    {% for key, values in data.items %}
    <tr>
        <td>{{key}}</td>
        <td>{{values}}</td>
    </tr>
    {% endfor %}
</table>

Take Picture Using POST and commands/execute

The basic format for most osc commands is osc/commands/execute. You then pass the specific command as a JSON payload like this: {"name": "camera.takePicture"}

def take_picture(request):
    url = f"{THETA_URL}commands/execute"
    payload = {"name": "camera.takePicture"}
    resp = requests.post(
                        url,
                        json=payload,
                        auth=(HTTPDigestAuth(THETA_ID, THETA_PASSWORD)))
                        
    data = resp.json()
    pprint.pprint(data)
    return render(request, 'commandhome.html', {'data': data})

There is extensive documentation for using the API commands here.

Generating List of Images

The images are listed using the same /osc/commands/execute and payload technique. This will return a listing of the URLs of the images that are on the camera.

def generate_image_list():
    url = f"{THETA_URL}commands/execute"
    command_string = "camera.listFiles"
    payload = {
                "name": command_string,
                "parameters": {
                    "fileType": "image",
                    "entryCount": 20,
                    "maxThumbSize": 0

                }}
    resp = requests.post(
                        url,
                        json=payload,
                        auth=(HTTPDigestAuth(THETA_ID, THETA_PASSWORD)))

    data = resp.json()
    imageEntries = data["results"]["entries"]
    images = []
    for imageEntry in imageEntries:
        print(imageEntry["fileUrl"])
        images.append(imageEntry["fileUrl"])
    return images

Downloading Images

As the images are accessible on the camera as URLs, you just have to implement a way to store the files to your local storage.

I’m saving the image with the same file name from the camera. The images are saved to the media directory of the Django project.

def getImage(url):
    imageName = url.split("/")[6]
    print("saving " + imageName + " to file")
    with open(f'{PROJECT_MEDIA_DIR}{imageName}', 'wb') as handle:
        response = requests.get(
                    url,
                    stream=True,
                    auth=(HTTPDigestAuth(THETA_ID, THETA_PASSWORD)))

        if not response.ok:
            print(response)
        for block in response.iter_content(1024):
            if not block:
                break
            handle.write(block)

To start the download process, call the function above.

def download_all_images(request):
    print("start download tester")
    images = generate_image_list()
    for imageLocation in images:
        getImage(imageLocation)
    return HttpResponse(f'wrote {str(len(images))} files')

Next Steps

The article Building a Web Site for 360 Images with Django, Bootstrap, and A-Frame explains how to process images on the server as well as display them in a gallery.

Continue extending this project to address all phases of the workflow:

  1. image capture
  2. image processing
  3. image management
  4. image display

Additional Code Examples

In addition to the code for this project, there are two other repos:

1 Like