Learning Dart with RICOH THETA API - Sample Code and Explanations

Getting Sample Code

The GitHub repository has been moved. To get the code examples, please fill out the form below.


According to GitHub’s The State of the Octoverse, Dart was the fastest growing language in 2019, growing faster than Go, Rust, and TypeScript.

The interest in Dart is largely driven by Flutter.

Growth of Dart

dart growth

JAXenter readers also ranked Dart as the most relevant language of 2019.

JAXenter poll

The IEEE SPECTRUM ranking puts Dart in the top 10 of trending languages.

Dart and RICOH THETA

As I was building documentation for the SC2 API, I decided to build the API tests with Dart. This project focuses on using Dart from the command line. After getting familiar with Dart language syntax, we plan to develop mobile app projects with Flutter in the future.

These tests were tested and found to work with THETA models SC2, V, and Z1.

RICOH THETA Dart HTTP Request tests

RICOH THETA API requests for models V, Z1, and SC2. API reference

screenshot

Usage

  1. connect workstation to THETA with camera in access point (AP) mode
  2. run main.dart file in bin with the appropriate command

Example with info

 dart bin/main.dart info

Instead of info, you can also use other commands:

Example with state

dart bin/main.dart state

Working commands:

  • info
  • state
  • takePicture
  • listFiles
  • getOptions

Explanation

POST example

response from THETA SC2

post state

Take Picture Example

If you send a payload such as {'name': 'camera.takePicture'} as part of your request, you must encode the body as JSON. You can use json.encode(your-payload-object) or the new jsonEncode() jsonEncode function - dart:convert library - Dart API

take picture

Test from THETA V. OK!

Test from THETA SC2. OK!

Response from SC@ shown below.

C:\Users\craigdev\Development\personal\dart>dart bin/main.dart
[]
200
{
  "name": "camera.takePicture",
  "id": "1588",
  "progress": {
    "completion": 0.0
  },
  "state": "inProgress"
}

List Files

https://api.ricoh/docs/theta-web-api-v2.1/commands/camera.list_files/

This shows a more complex nested payload with parameters.

Response

$ dart bin/main.dart 
[]
200
{
  "name": "camera.listFiles",
  "results": {
    "entries": [
      {
        "dateTimeZone": "2020:03:18 17:12:32-07:00",
        "fileUrl": "http://192.168.1.1/files/150100525831424d42079d18e0b6c300/100RICOH/R0010024.JPG",
        "height": 2688,
        "isProcessed": true,
        "name": "R0010024.JPG",
        "previewUrl": "",
        "_projectionType": "Equirectangular",
        "size": 4362617,
        "_thumbSize": 2749,
        "width": 5376
      },

Get Options

The camera options you want to get need to be specified individually in an array. I do not think you can get all the options with a wildcard or “all” specification.

Format of the data request is below.

var url ='http://192.168.1.1/osc/commands/execute';

  Map data = {
    'name': 'camera.getOptions',
    'parameters': {
      'optionNames': [
        "iso",
        "isoSupport"
      ]
    }

Response from a THETA SC2 running firmware 1.20 is shown below.

{
  "name": "camera.getOpions",
  "state": "done",
  "results": {
    "options": {
      "iso": 0,
      "isoSupport": [
        64,
        80,
        100,
        125,
        160,
        200,
        250,
        320,
        400,
        500,
        640,
        800,
        1000,
        1250,
        1600,
        2000,
        2500,
        3200
      ]
    }
  }
}

Addtional Options

In my tests, there are significant differences between the THETA V options and the options for SC2. In your tests, you can try each option individually to see what is supported.

Note that in the test of the SC2 below, the previewFormat is not returning the correct values.

The payload is:

Map data = {
    'name': 'camera.getOptions',
    'parameters': {
      'optionNames': [
        "offDelay",
        "sleepDelay",
        "remainingSpace",
        "_colorTemperature",
        "previewFormat"
      ]
    }
  };

The response from a THETA SC2 running firmware 1.20 is shown below. Note that the previewFormat is giving 0 values. This API is likely not supported at the moment.

{
  "name": "camera.getOpions",
  "state": "done",
  "results": {
    "options": {
      "offDelay": 65535,
      "sleepDelay": 65535,
      "remainingSpace": 2168410112,
      "_colorTemperature": 2500,
      "previewFormat": {
        "width": 0,
        "height": 0
      },
      "framerate": 0
    }
  }
}

For comparison, this is the response from a THETA V. See the difference in the previewFormat information.

options output

Camera Firmware Tested

  • Z1 1.31.1
  • RICOH THETA SC 1.20
  • V 3.21.1

sc2 screenshot

Troubleshooting Camera

Testing Connection with GET info

The simplest command to the camera is GET info.

You can test it in a browser, curl, Postman. In the test program, you can look for the URL below.

String url = 'http://192.168.1.1/osc/info';

If you are having problems getting a camera connection and want to test your code with a known working API that returns a single JSON object, you can use a public Internet test server to return a single JSON object and print it out.

// String url = 'https://swapi.co/api/people/1';
// String url = 'https://jsonplaceholder.typicode.com/users/1';

Configuration and Installation

  1. install dart
  2. clone this repo
  3. run pub get to install dependencies
$ pub get
Resolving dependencies... (1.2s)
Downloading args 1.5.3...
Downloading http 0.12.0+4...
Downloading pedantic 1.9.0...
Downloading async 2.4.0...
Downloading source_span 1.6.0...
Downloading charcode 1.1.3...
Downloading meta 1.1.8...
Got dependencies!

Additional Screenshots

THETA V

THETA V Info

References

Notes

1 Like

This is very useful. Following the instructions, I downloaded Dart on a Windows machine, cloned your repo listed here. I connected my laptop to a Z1 and an SC2 (alternating). And I was able to run state, info, listFiles, getOptions, takePicture. Then opening up the files with VS Code, I could edit the commands to use different options.

Really cool.

I’m looking to spend some more time with this. If anyone else is working with it, please let me know. I’d be interested to see your results.

EDIT: The only real issue I had so far was connecting my laptop to my SC2. This is probably a basic mistake, and doesn’t really have to do with the information posted by @codetricity. But I’m noting here in case other people run into it. To connect to the THETA, I made sure the Wi-Fi was on (blinking Wi-Fi icon) and found it on the list of networks. But when it asked for a password, it first asked for a PIN. I didn’t really notice the difference. It would not accept the password (the serial number, just the numerical digits, which is on the bottom of the camera and is also the name of the network). If it’s asking for a PIN, make sure you click on “Connect using a security key instead”

Using a PIN won’t work

Using the network security key (serial number, just the numerical digits) will work

UPDATED: I’m testing with a Z1, an SC2, and a V. Posting a few differences between the 3 models.

Running dart bin/main.dart getMetadata shows some differences:

  • Overall order is different between the models. V list appears to be alphabetically ordered. SC2 is not.
  • XMP data values are different
    • ProjectionType is equirectangular for V
    • CroppedAreaImageHeightPixels is 0 for SC2, 2688 for V
    • CroppedAreaImageWidthPixels is 0 for SC2, 5376 for V
    • FullPanoWidthPixels is 0 for SC2, 5376 for V
    • FullPanoHeightPixels is 0 for SC2, 2688 for V
  • exif data values are different
    • ExifVersion is blank for SC2, 0230 for V
    • DateTime is blank for SC2, 2020:03:24 11:05:24 for V
    • quite a few more
  • MISSING
    • V does not have GPSLattitudeRef, GPSLatitude, GPSLongitudeRef, GPSLongitude and MakerNote - 27 total for SC2, 22 total for V

SC2

V

Z1

Z1 gets an error that I haven’t figured out yet

Also, noticed that running state on the V shows a COMPASS CALIBRATION error that you can’t see otherwise, since there’s no OLED, and that won’t information show up in the RICOH THETA mobile app either.

1 Like

I extended the code to include an example of downloading the last image file taken. Here’s the results of the image downloaded with an SC2.

You can test this out with:

dart bin/main.dart downloadFile

If you’ve already cloned the repo, you’ll need to do this:

git pull
pub get

I’ve updated the document for the SC2 API with this new information.

BTW, the code example uses the dart http package, which looks like the same package that Flutter developers are using. See the example below.

Flutter Tests

From file using an SC2 image.

Connected to THETA V with Wi-Fi

Pulling image from camera

Testing with Pixel 2

Native Android app. File is being accessed directly from camera.

 Image.network('http://192.168.1.1/files/150100525831424d42079d18e0b6c300/100RICOH/R0010028.JPG',
                fit: BoxFit.fill,

Confirmed to Work with SC2

@codetricity Thanks for updating the repo with the downloadFile command. I did a git pull and a pub get and (after realizing I needed to do a git stash of some local edits that I made but didn’t want to merge right away) it worked on the first try.

1 Like

In addition to testing the API, there are several other things you can do to mock up the mobile app interface.

Color Palette

If we use a green theme to differentiate the app from the official RICOH app, we need a color palette

Create a palette - Coolors

Or Material Palette https://www.materialpalette.com/

Interface Mockup

Consider something like Figma https://www.figma.com/

I am using Material Material Design

These icons are built into the system https://material.io/resources/icons/?style=baseline

A good place to start is the color palette.

Update on takePicture

The previous button was a mockup, but I just connected the code in with one line it works.

Here’s the code for the button.

        floatingActionButton: FloatingActionButton.extended(
          onPressed: () {
            print("button pressed");
            takePicture();
          },
          label: Text('THETA Picture'),
          backgroundColor: Color(0xff00aa2a),
          icon: Icon(Icons.camera_alt),

take_picture.dart

successfully tested with Flutter button (FloatingActionButton). Note that I’m using jsonEncode on the body. This is the exact same function used in the command line app. No modication needed. Nice.

import 'dart:async';
import 'dart:convert';
import 'package:http/http.dart' as http;


Future<http.Response> takePicture () async {
  var url ='http://192.168.1.1/osc/commands/execute';

  Map data = {
    'name': 'camera.takePicture'
  };
  //encode Map to JSON
  var body = jsonEncode(data);

  var response = await http.post(url,
      headers: {"Content-Type": "application/json;charset=utf-8"},
      body: body
  );
  print("${response.statusCode}");
  print("${response.body}");
  return response;
}

Update on getting image metadata

Command line now works. We can pull the GPS information and other data. I have tested only on THETA V. Please test with SC2.

$ dart bin/main.dart getMetadata
200
{
   "name": "camera._getMetadata",


1 Like

Some info on why we are working with Dart, according to Redmonk developer-focused analyst firm.

Dart (+3): Lastly, we have the case of Dart. It is not a language that has been commented on in this space in some time, due to its middling historical performance on these rankings. As correctly predicted by at least one person, however, Dart has made some recent gains that are roughly correlated with a spike in popularity of the UI toolkit Flutter. Eighteen months ago, Dart checked in at #33. Since the Dart-based Flutter went 1.0 six months after that, the language has jumped all the way up to #24 in the latest rankings. It was argued in this space nearly a decade ago that frameworks lead adoption, and Dart’s rapid rise after years of stagnation is one example of this phenomenon at work. If Dart is now powered in large part by Flutter, however, the obvious question is how far Flutter can take the language up our charts.

At the current time, there are two code bases. The one we’re primarily working with is the Dart code that actually connects to the camera and runs the API. This is a command line tool for testing.

You can request for the command line code at the link below

The mobile app code for Flutter is primarily layout code that we’re using to get the design of the mobile app. The design is things like color, font, shape of buttons. For this, we are using Flutter. Currently, the Flutter code does not connect to the camera. However, we’ve tested it with the Dart code and it looks like most of the code snippets will drop in without modification. We can grab the images from the camera and take a picture with a Flutter app on a physical mobile device.

However, as we’re still deciding on color and fonts, we’re not connecting the Flutter code to the camera at this time.

As a test to see how difficult it is to build a mobile app with Flutter, I asked my teenage daughter to give it a try. She used Floating Action Buttons (FAB) and was able to build the app below in a few hours. The buttons are not connected to the Dart code at this time.

Her code is here:

The only file you need to look at is main.dart. The code for that file is here:

As you can see, the current code uses a StatelessWidget. She’ll need to change this into a StatefulWidget to get the response from the camera onto the screen.

How to Test

Start Android Studio. Check out project from Version Control.

image

Select git.

Put repo of URL above into Android Studio.

image

Clone it.

Do not create a new Android Studio project.

Open flutter project in Android Studio.

image

Get dependencies

image

Plug physical device into computer.

Select physical device.

image

Demo on Physical Device

This mobile app design is specifically for the SC2 light-pink model. The sample picture was taken by the developer with a THETA S during a family outing.

Steps

  • Create basic Flutter app with Scaffold Widget
  • Inside Scaffold make Column widget
  • The first child of the Column is the Image Widget (I used an AssetImage)
  • The next 3 children are Row Widges
  • Within each Row I created multiple FloatingActionButtons

Update March 23, 2020

  • Implemented commands for six of the buttons.
  • Download file not working
  • Uploaded changes to GitHub

Update March 24, 2020

The next step is to add a text box below buttons to display the output of the buttons. In the current version we just have placeholder text. Code on GitHub is updated. At the momemnt, we’re using a RichText widget in dart.


               RichText(
                 text: TextSpan(
                   text: 'Lorem ipsum dolor sit amet, consectetur adipiscing elit,'
                       ' sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. '
                       'Porta lorem mollis aliquam ut porttitor leo. In nisl nisi scelerisque eu ultrices vitae auctor eu. '
                       'In cursus turpis massa tincidunt dui ut ornare lectus sit.',
                   style: TextStyle(color: Color(0xff32afa9))
                 ),
            )

Update march 24, 2020 afternoon

  • camera output now displays onto front main text panel when button is pressed
  • output is not formatted and is cut off at 500 characters
  • new technique is to implement state into the Flutter program

image

State seems easier to implement than in React at this stage. However, the concept looks similar.

The code is implemented on GitHub

Update March 24, 2020 night

Separate GitHub repo for standalone test.

I added some details and screenshots on V, SC2 and Z1 API data differences between the models. Edited a previous post but noting it here, since this thread has gotten longer.

Did you use an image from the V that was taken with a mobile phone? Without the mobile phone, the V will not have GPS information in the metadata.

I’m still struggling with interface ideas. At the moment, we have a mobile app that can access the camera API. We still need to figure out what to build.

My current idea:

  • technical tester for developers that want to inspect camera and image settings
  • features for photographers that can’t be accessed with the official mobile app

features:

  • camera reset
  • disable/enable top/bottom correction on still images

Are these in the official mobile app?

Z1-specific

might just be a row of buttons, similar to below.

iOS 13.4 just released

This new upgrade should resolve the problem with the physical iOS device testing with Flutter. I’m upgrading Xcode now to version 11.4 so that it works with iOS 13.4

now running on iPhone 7 with iOS 13.4.

Update April 8, 2020

now with rounded corners.

Update April 10, 2020

Added Dart command to print out version of firmware and camera model.

You can get the updated code at the link below.

Simple example to show how to Map the JSON response with jsonDecode.

import 'dart:convert';
import 'package:http/http.dart' as http;

void firmwareVersion() async {

  String url = 'http://192.168.1.1/osc/info';
  var response = await http.get(url);

  Map<String, dynamic> info = jsonDecode(response.body);
  String firmwareVersion = info['firmwareVersion'];
  String model = info['model'];
  print("Running firmware version $firmwareVersion on $model");
}

Updated Example Getting Status of Image File Ready to Download

updated: April 11, 2020

Download Libraries

April 12, 2020

Download is handled differently on a command line desktop program compared to a mobile app. I’m going to first combine the steps on the command line, then look at these two libraries for iOS/Android.

April 23, 2020

Add increased GPS accuracy to list of features.

May 11, 2020
Put features into Google Sheet