Time Recording with THETA Plug-in and IFTTT (Introductory Edition)
Time Recording with THETA Plug-in and IFTTT (Introductory Edition)
Introduction
Hello, this is @yomura_ from RICOH.
I’ve made a simple time recording mechanism with the RICOH THETA plug-in and IFTTT.
I’m starting with an introductory edition.
About RICOH THETA Plug-ins
For those who are not familiar with THETA plug-ins, please see here.
About IFTTT
IFTTT is a service that connects external services in the form of IF This Then That
, and handles a variety of services from SNS to IoT devices.
In this article, This
is called a trigger, That
is called an action, and the combination of two is called an applet.
I have created an applet that performs the action of adding a new row to Google Sheets
, by using the Webhooks
service as a trigger.
Creating an Applet
An applet is created following the steps below.
- Create a new applet from https://ifttt.com/create
- Select this (trigger) in
Webhooks
- Select
Receive a web request
and inputEvent Name
- This time, I used
theta_button_pressed
(This name will be used later.)
- Select
- Select
Google Sheets
for that (action) - Select
Add row
to spreadsheet, and input each item (Formatted rows will be mentioned later)
This completes the creation of an applet that adds a row to the spreadsheet when sending POST to the specified URL.
About Formatted Rows
The format of a row to be recorded can be changed. In addition, the following 5 variables can be embedded.
OccurredAt
: Event occurrence time (recording this is the purpose of this blog.)EventName
: Event name when creating a Webhook trigger.Value1
: arbitrary valueValue2
: arbitrary valueValue3
: arbitrary value
Implementation
This time, I used POST to the URL which triggers the IFTTT applet and the action to execute.
The sample source code for this plug-in is available on GitHub.
WebhookTast
WebhookTast.kt
package com.theta360.iftttsample.task
import android.util.Log
import com.google.gson.Gson
import com.google.gson.JsonObject
import okhttp3.*
import java.net.HttpURLConnection.HTTP_OK
class WebhookTask(private val url: String) {
private val httpClient = OkHttpClient()
fun request(): Boolean {
val body = JsonObject().apply {
addProperty("value1", "hoge")
addProperty("value2", "fuga")
addProperty("value3", "piyo")
}
val requestBody = RequestBody.create(
MediaType.parse("application/json; charset=UTF-8"), GSON.toJson(body))
val request = Request.Builder()
.url(url)
.post(requestBody)
.addHeader("Accept", "application/json")
.addHeader("X-XSRF-Protected", "1")
.build()
Log.d(TAG, "START - http request")
val response = httpClient.newCall(request).execute()
Log.d(TAG, "FINISH - http request")
Log.d(TAG, "Status code: ${response.code()}")
val responseBody = response.body()
if (responseBody != null)
Log.d(TAG, responseBody.string())
return response.code() == HTTP_OK
}
companion object {
private val TAG: String = WebhookTask::class.java.simpleName
private val GSON = Gson()
}
}
Add Arbitrary Character String
A character string in the spreadsheet can be recorded by specifying the character string in value1
, value2
, value3
keys in JSON in the request body.
I couldn’t think of a good way to use this, so it looks like this.
val body = JsonObject().apply {
addProperty("value1", "hoge")
addProperty("value2", "fuga")
addProperty("value3", "piyo")
}
MainActivity
MainActivity.java
package com.theta360.iftttsample;
import android.os.Bundle;
import android.util.Log;
import android.view.KeyEvent;
import com.theta360.iftttsample.task.TakePictureTask;
import com.theta360.iftttsample.task.TakePictureTask.Callback;
import com.theta360.iftttsample.task.WebhookTask;
import com.theta360.pluginlibrary.activity.PluginActivity;
import com.theta360.pluginlibrary.callback.KeyCallback;
import com.theta360.pluginlibrary.receiver.KeyReceiver;
import com.theta360.pluginlibrary.values.LedColor;
import com.theta360.pluginlibrary.values.LedTarget;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.atomic.AtomicBoolean;
public class MainActivity extends PluginActivity {
private static final String TAG = MainActivity.class.getSimpleName();
private static final String WEBHOOK_KEY = "write ifttt webhook key here";
private static final String WEBHOOK_EVENT_NAME = "write ifttt webhook event name here";
private static final String WEBHOOK_URL = "https://maker.ifttt.com/trigger/" + WEBHOOK_EVENT_NAME + "/with/key/" + WEBHOOK_KEY;
private final ExecutorService executor = Executors.newSingleThreadExecutor();
private AtomicBoolean isProceeding = new AtomicBoolean();
private WebhookTask webhookTask = new WebhookTask(WEBHOOK_URL);
private TakePictureTask.Callback mTakePictureTaskCallback = new Callback() {
@Override
public void onTakePicture(String fileUrl) {
}
};
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
// Set enable to close by pluginlibrary, If you set false, please call close() after finishing your end processing.
setAutoClose(true);
// Set a callback when a button operation event is acquired.
setKeyCallback(new KeyCallback() {
@Override
public void onKeyDown(int keyCode, KeyEvent event) {
if (keyCode == KeyReceiver.KEYCODE_CAMERA) {
/*
* To take a static picture, use the takePicture method.
* You can receive a fileUrl of the static picture in the callback.
*/
// new TakePictureTask(mTakePictureTaskCallback).execute();
if (isProceeding.get()) {
Log.d(TAG, "Skip to post webhook.");
return;
}
executor.submit(() -> {
isProceeding.set(true);
notificationAudioOpen();
try {
if (webhookTask.request()) {
Log.d(TAG, "Succeeded to post webhook.");
notificationAudioClose();
}
} catch (Exception e) {
Log.e(TAG, "Failed to post webhook.", e);
notificationAudioWarning();
} finally {
isProceeding.set(false);
}
});
}
}
@Override
public void onKeyUp(int keyCode, KeyEvent event) {
/**
* You can control the LED of the camera.
* It is possible to change the way of lighting, the cycle of blinking, the color of light emission.
* Light emitting color can be changed only LED3.
*/
notificationLedBlink(LedTarget.LED3, LedColor.BLUE, 1000);
}
@Override
public void onKeyLongPress(int keyCode, KeyEvent event) {
}
});
}
@Override
protected void onResume() {
super.onResume();
if (isApConnected()) {
}
}
@Override
protected void onPause() {
// Do end processing
//close();
super.onPause();
}
}
Webhook Key and Event Name Setting
It is necessary to include the IFTTT Webhook key and Webhook event name in the URL.
For WEBHOOK_EVENT_NAME
, enter the Event Name
that was set when the applet was created.
WEBHOOK_KEY
can be verified from Documentation
at https://ifttt.com/maker_webhooks
private static final String WEBHOOK_KEY = "write ifttt webhook key here";
private static final String WEBHOOK_EVENT_NAME = "write ifttt webhook event name here";
Executing a Task
Executors.newSingleThreadExecutor()
was used for asynchronous processing.
Generate another thread with this executor
and execute asynchronous processing.
import java.util.concurrent.ExecutorService;
public class MainActivity extends PluginActivity {
private ExecutorService executor = Executors.newSingleThreadExecutor();
...
The created WebhookTask
is executed inside the onKeyDown
method.
With this, when the THETA shutter button is pressed, a POST request is sent to the specified URL.
executor.submit(() -> {
isProceeding.set(true);
notificationAudioOpen();
try {
if (webhookTask.request()) {
Log.d(TAG, "Succeeded to post webhook.");
notificationAudioClose();
}
} catch (Exception e) {
Log.e(TAG, "Failed to post webhook.", e);
notificationAudioWarning();
} finally {
isProceeding.set(false);
}
});
Check During Task Execution
The AtomicBoolean type variable isProceeding
is used as a flag to indicate that it is being processed. Because of this, if the KEYCODE_CAMERA
event occurs before the task is completed, it will skip proceeding.
if (keyCode == KeyReceiver.KEYCODE_CAMERA) {
if (isProceeding.get()) {
Log.d(TAG, "Skip to post webhook.");
return;
}
...
Execution Result
When THETA plug-in is activated and the shutter button is pressed, a row is added to the spreadsheet.
Conclusion
In this blog, I have introduced pressing the THETA shutter button directly to record a new row in a spreadsheet.
My next challenge will be to find a different way from pressing the shutter button directly to record a new row in a spreadsheet.
Application 1: Combination with OpenCV
Because the image processing library OpenCV can be used with THETA, it would be convenient if it could detect the movement of people and record it to a spreadsheet.
If pictures are timed and used with motion detection to recognize people, it may be possible to easily manage entry and exit of a room.
More information here.
Application 2: Combination with the Bluetooth button
BLE (Bluetooth Low Energy) radio waves can be received by the THETA plug-in.
It appears that it can be used in various ways, such as recording when a smartphone is nearby.
More information here (in Japanese).