From f8dbed025dccf292535f60c979fc76b64dc84115 Mon Sep 17 00:00:00 2001 From: Sano Chihiro Date: Mon, 1 Sep 2025 23:13:02 +0900 Subject: [PATCH 01/31] initial commit From 4d286d90efceaa7bc6cb7f6d7d2a9a6868a21a1a Mon Sep 17 00:00:00 2001 From: Sano Chihiro Date: Fri, 5 Sep 2025 02:22:35 +0900 Subject: [PATCH 02/31] =?UTF-8?q?[WIP]=E5=88=9D=E6=9C=9F=E5=8C=96=E5=87=A6?= =?UTF-8?q?=E7=90=86=E3=82=92=E8=A1=8C=E3=81=86=E9=96=A2=E6=95=B0=E3=82=92?= =?UTF-8?q?=E4=BD=9C=E6=88=90=E4=B8=AD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- theta_wireless.py | 61 +++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 61 insertions(+) create mode 100644 theta_wireless.py diff --git a/theta_wireless.py b/theta_wireless.py new file mode 100644 index 0000000..2bb8030 --- /dev/null +++ b/theta_wireless.py @@ -0,0 +1,61 @@ +"""Theta Web APIを利用した関数""" + +from enum import Enum +import requests + +class ThetaConstans(str, Enum): + THETA_IP = "192.168.1.1" + EXECUTE_URL = f"http://{THETA_IP}/osc/commands/execute" + STATUS_URL = f"http://{THETA_IP}/osc/commands/status" + HEADERS = {"Content-Type": "application/json;charset=utf-8"} + +class Name(str, Enum): + SET_OPTIONS = "camera.setOptions" + GET_OPTIONS = "camera.getOptions" + TAKE_PICTURE = "camera.takePicture" + +class Parameter(str, Enum): + OPTIONS = "options" + OPTION_NAMES = "optionNames" + + +def _create_payload(name: str, parameters: dict[str, any]) -> dict[str, any]: + return {"name": name, "parameters": parameters} + + +def camera_init() -> None: + """ + カメラの初期化を行う関数 + """ + payload = _create_payload( + Name.SET_OPTIONS, + {Parameter.OPTIONS: ["captureMode":"image", "exposureProgram":1]} + ) + + +payload = { + "name": "camera.setOptions", + "parameters": {"options": {"captureMode": "image"}}, +} + +resp = requests.post(url, json=payload, headers=headers) +print(resp.json()) + +payload = { + "name": "camera.setOptions", + "parameters": {"options": {"exposureProgram": 1}}, +} + +resp = requests.post(url, json=payload, headers=headers) +print(resp.json()) + +# 確認したいオプションを parameters に必ず入れる +payload = { + "name": "camera.getOptions", + "parameters": { + "optionNames": ["iso", "shutterSpeed", "aperture", "_colorTemperature"] + }, +} + +resp = requests.post(url, json=payload, headers=headers) +print(resp.json()) From 9705ec0e151b4a4427ed882f3a70fd56d22e8e09 Mon Sep 17 00:00:00 2001 From: Sano Chihiro Date: Fri, 5 Sep 2025 02:25:41 +0900 Subject: [PATCH 03/31] =?UTF-8?q?[Fix]syntax=20error=E4=BF=AE=E6=AD=A3?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 関数自体は出来上がってないけど --- theta_wireless.py | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/theta_wireless.py b/theta_wireless.py index 2bb8030..dd9c6df 100644 --- a/theta_wireless.py +++ b/theta_wireless.py @@ -3,17 +3,20 @@ from enum import Enum import requests + class ThetaConstans(str, Enum): THETA_IP = "192.168.1.1" EXECUTE_URL = f"http://{THETA_IP}/osc/commands/execute" STATUS_URL = f"http://{THETA_IP}/osc/commands/status" HEADERS = {"Content-Type": "application/json;charset=utf-8"} + class Name(str, Enum): SET_OPTIONS = "camera.setOptions" GET_OPTIONS = "camera.getOptions" TAKE_PICTURE = "camera.takePicture" + class Parameter(str, Enum): OPTIONS = "options" OPTION_NAMES = "optionNames" @@ -29,7 +32,7 @@ def camera_init() -> None: """ payload = _create_payload( Name.SET_OPTIONS, - {Parameter.OPTIONS: ["captureMode":"image", "exposureProgram":1]} + {Parameter.OPTIONS: {"captureMode": "image", "exposureProgram": 1}}, ) From d143755108bc6eb211cc66c3d28aa6f6544d0f86 Mon Sep 17 00:00:00 2001 From: Sano Chihiro Date: Fri, 5 Sep 2025 12:12:50 +0900 Subject: [PATCH 04/31] [Add] add vs code file to gitignore --- .gitignore | 1 + 1 file changed, 1 insertion(+) diff --git a/.gitignore b/.gitignore index b7faf40..b140be7 100644 --- a/.gitignore +++ b/.gitignore @@ -205,3 +205,4 @@ cython_debug/ marimo/_static/ marimo/_lsp/ __marimo__/ +.vscode/settings.json From 1ed18eaee84b452d5b04d7794fb611e9518adf95 Mon Sep 17 00:00:00 2001 From: Sano Chihiro Date: Fri, 5 Sep 2025 13:16:20 +0900 Subject: [PATCH 05/31] =?UTF-8?q?[WIP]=E9=96=A2=E6=95=B0=E4=BD=9C=E6=88=90?= =?UTF-8?q?=E4=B8=AD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- theta_wireless.py | 83 +++++++++++++++++++++++++++++------------------ 1 file changed, 51 insertions(+), 32 deletions(-) diff --git a/theta_wireless.py b/theta_wireless.py index dd9c6df..a6ecabf 100644 --- a/theta_wireless.py +++ b/theta_wireless.py @@ -21,44 +21,63 @@ class Parameter(str, Enum): OPTIONS = "options" OPTION_NAMES = "optionNames" +class ThetaWirelessResponse(dict[str,str], Enum): + TIMEOUT = {"error":"time_out"} -def _create_payload(name: str, parameters: dict[str, any]) -> dict[str, any]: - return {"name": name, "parameters": parameters} +def _create_payload(name: str, parameters: dict[str, any] | None = None) -> dict[str, any]: + if (dict is None): + return {"name":name} + else: + return {"name": name, "parameters": parameters} -def camera_init() -> None: + +def set_options(parameters:dict[str, any]) -> dict[str, any]: """ - カメラの初期化を行う関数 + Thetaへオプションの設定を行う """ payload = _create_payload( Name.SET_OPTIONS, - {Parameter.OPTIONS: {"captureMode": "image", "exposureProgram": 1}}, + {Parameter.OPTIONS: parameters}, ) - -payload = { - "name": "camera.setOptions", - "parameters": {"options": {"captureMode": "image"}}, -} - -resp = requests.post(url, json=payload, headers=headers) -print(resp.json()) - -payload = { - "name": "camera.setOptions", - "parameters": {"options": {"exposureProgram": 1}}, -} - -resp = requests.post(url, json=payload, headers=headers) -print(resp.json()) - -# 確認したいオプションを parameters に必ず入れる -payload = { - "name": "camera.getOptions", - "parameters": { - "optionNames": ["iso", "shutterSpeed", "aperture", "_colorTemperature"] - }, -} - -resp = requests.post(url, json=payload, headers=headers) -print(resp.json()) + try: + response = requests.post( + url=ThetaConstans.EXECUTE_URL, + json=payload, + headers=ThetaConstans.HEADERS, + timeout=10, + ) + return response.json + except requests.exceptions.Timeout: + return ThetaWirelessResponse.TIMEOUT + +def get_options(option_names:set[str]) -> dict[str, any]: + """ + Thetaに設定したオプションの情報を取得する + """ + payload = _create_payload( + Name.GET_OPTIONS, + {Parameter.OPTION_NAMES:option_names} + ) + + try: + response = requests.post( + url=ThetaConstans.EXECUTE_URL, + json=payload, + headers=ThetaConstans.HEADERS, + timeout=10 + ) + return response.json + except requests.exceptions.Timeout: + return ThetaWirelessResponse.TIMEOUT + + +def take_picture() -> dict[str, any]: + """ + Theta Web APIを用いて撮影 + """ + payload = _create_payload(Name.TAKE_PICTURE) + response = requests.post(ThetaConstans.EXECUTE_URL, json=payload, headers=ThetaConstans.HEADERS, timeout=10) + response.raise_for_status() + return response.json() From 5a49484738317a71a94147dfd877df0495506ea9 Mon Sep 17 00:00:00 2001 From: Sano Chihiro Date: Fri, 5 Sep 2025 13:18:09 +0900 Subject: [PATCH 06/31] =?UTF-8?q?[Fix]=E8=A1=8C=E6=95=B0=E9=95=B7=E3=81=99?= =?UTF-8?q?=E3=81=8E=E5=95=8F=E9=A1=8C=E3=81=AB=E5=AF=BE=E5=BF=9C?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- theta_wireless.py | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/theta_wireless.py b/theta_wireless.py index a6ecabf..f3ddd27 100644 --- a/theta_wireless.py +++ b/theta_wireless.py @@ -78,6 +78,11 @@ def take_picture() -> dict[str, any]: Theta Web APIを用いて撮影 """ payload = _create_payload(Name.TAKE_PICTURE) - response = requests.post(ThetaConstans.EXECUTE_URL, json=payload, headers=ThetaConstans.HEADERS, timeout=10) + response = requests.post( + ThetaConstans.EXECUTE_URL, + json=payload, + headers=ThetaConstans.HEADERS, + timeout=10 + ) response.raise_for_status() return response.json() From ba0be6a2fffd53ef99d8050c564820d11eca3377 Mon Sep 17 00:00:00 2001 From: Sano Chihiro Date: Fri, 5 Sep 2025 13:20:22 +0900 Subject: [PATCH 07/31] =?UTF-8?q?[Fix]return=E7=9B=B4=E5=BE=8C=E3=81=AEels?= =?UTF-8?q?e=E3=82=92=E5=89=8A=E9=99=A4?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- theta_wireless.py | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/theta_wireless.py b/theta_wireless.py index f3ddd27..3970f8d 100644 --- a/theta_wireless.py +++ b/theta_wireless.py @@ -28,8 +28,7 @@ class ThetaWirelessResponse(dict[str,str], Enum): def _create_payload(name: str, parameters: dict[str, any] | None = None) -> dict[str, any]: if (dict is None): return {"name":name} - else: - return {"name": name, "parameters": parameters} + return {"name": name, "parameters": parameters} def set_options(parameters:dict[str, any]) -> dict[str, any]: @@ -60,7 +59,7 @@ def get_options(option_names:set[str]) -> dict[str, any]: Name.GET_OPTIONS, {Parameter.OPTION_NAMES:option_names} ) - + try: response = requests.post( url=ThetaConstans.EXECUTE_URL, @@ -71,7 +70,7 @@ def get_options(option_names:set[str]) -> dict[str, any]: return response.json except requests.exceptions.Timeout: return ThetaWirelessResponse.TIMEOUT - + def take_picture() -> dict[str, any]: """ From e3c886d0db38af76a4f046dbaefc7b29768daf7c Mon Sep 17 00:00:00 2001 From: Sano Chihiro Date: Fri, 5 Sep 2025 13:24:13 +0900 Subject: [PATCH 08/31] =?UTF-8?q?=E5=86=85=E9=83=A8=E3=81=A7=E3=81=97?= =?UTF-8?q?=E3=81=8B=E4=BD=BF=E3=81=86=E4=BA=88=E5=AE=9A=E3=81=AE=E3=81=AA?= =?UTF-8?q?=E3=81=84Enum=E3=81=AE=E5=91=BD=E5=90=8D=E3=82=92=E5=A4=89?= =?UTF-8?q?=E6=9B=B4?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- theta_wireless.py | 37 ++++++++++++++++++++----------------- 1 file changed, 20 insertions(+), 17 deletions(-) diff --git a/theta_wireless.py b/theta_wireless.py index 3970f8d..13726b5 100644 --- a/theta_wireless.py +++ b/theta_wireless.py @@ -4,24 +4,24 @@ import requests -class ThetaConstans(str, Enum): +class _ThetaConstans(str, Enum): THETA_IP = "192.168.1.1" EXECUTE_URL = f"http://{THETA_IP}/osc/commands/execute" STATUS_URL = f"http://{THETA_IP}/osc/commands/status" HEADERS = {"Content-Type": "application/json;charset=utf-8"} -class Name(str, Enum): +class _Name(str, Enum): SET_OPTIONS = "camera.setOptions" GET_OPTIONS = "camera.getOptions" TAKE_PICTURE = "camera.takePicture" -class Parameter(str, Enum): +class _Parameter(str, Enum): OPTIONS = "options" OPTION_NAMES = "optionNames" -class ThetaWirelessResponse(dict[str,str], Enum): +class _ThetaWirelessResponse(dict[str,str], Enum): TIMEOUT = {"error":"time_out"} @@ -36,51 +36,54 @@ def set_options(parameters:dict[str, any]) -> dict[str, any]: Thetaへオプションの設定を行う """ payload = _create_payload( - Name.SET_OPTIONS, - {Parameter.OPTIONS: parameters}, + _Name.SET_OPTIONS, + {_Parameter.OPTIONS: parameters}, ) try: response = requests.post( - url=ThetaConstans.EXECUTE_URL, + url=_ThetaConstans.EXECUTE_URL, json=payload, - headers=ThetaConstans.HEADERS, + headers=_ThetaConstans.HEADERS, timeout=10, ) return response.json except requests.exceptions.Timeout: - return ThetaWirelessResponse.TIMEOUT + return _ThetaWirelessResponse.TIMEOUT def get_options(option_names:set[str]) -> dict[str, any]: """ Thetaに設定したオプションの情報を取得する """ payload = _create_payload( - Name.GET_OPTIONS, - {Parameter.OPTION_NAMES:option_names} + _Name.GET_OPTIONS, + {_Parameter.OPTION_NAMES:option_names} ) try: response = requests.post( - url=ThetaConstans.EXECUTE_URL, + url=_ThetaConstans.EXECUTE_URL, json=payload, - headers=ThetaConstans.HEADERS, + headers=_ThetaConstans.HEADERS, timeout=10 ) return response.json except requests.exceptions.Timeout: - return ThetaWirelessResponse.TIMEOUT + return _ThetaWirelessResponse.TIMEOUT def take_picture() -> dict[str, any]: """ Theta Web APIを用いて撮影 """ - payload = _create_payload(Name.TAKE_PICTURE) + payload = _create_payload( + _Name.TAKE_PICTURE + ) + response = requests.post( - ThetaConstans.EXECUTE_URL, + _ThetaConstans.EXECUTE_URL, json=payload, - headers=ThetaConstans.HEADERS, + headers=_ThetaConstans.HEADERS, timeout=10 ) response.raise_for_status() From 17b38fa47d03edcb704d11d6aad031cd94e71bdb Mon Sep 17 00:00:00 2001 From: Sano Chihiro Date: Sun, 7 Sep 2025 01:24:00 +0900 Subject: [PATCH 09/31] =?UTF-8?q?[Update]=E4=BE=8B=E5=A4=96=E3=82=AF?= =?UTF-8?q?=E3=83=A9=E3=82=B9=E3=82=92=E8=BF=BD=E5=8A=A0=E3=81=97=E3=80=81?= =?UTF-8?q?=E4=BE=8B=E5=A4=96=E3=81=8C=E7=99=BA=E7=94=9F=E3=81=99=E3=82=8B?= =?UTF-8?q?=E3=82=88=E3=81=86=E5=A4=89=E6=9B=B4?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- theta_wireless.py | 116 +++++++++++++++++++++++++++++++++++----------- 1 file changed, 88 insertions(+), 28 deletions(-) diff --git a/theta_wireless.py b/theta_wireless.py index 13726b5..093c775 100644 --- a/theta_wireless.py +++ b/theta_wireless.py @@ -21,8 +21,26 @@ class _Parameter(str, Enum): OPTIONS = "options" OPTION_NAMES = "optionNames" -class _ThetaWirelessResponse(dict[str,str], Enum): - TIMEOUT = {"error":"time_out"} +class CameraError(Exception): + """全てのカメラ関連エラーの基底クラス""" + +class CameraTimeout(CameraError): + """カメラ操作のタイムアウトした場合の例外""" + +class CameraInternalError(CameraError): + """Open Spherical Camera APIがエラーを返した場合の例外""" + + def __init__(self, code:str, message:str, response_json:dict[str,any]=None): + """ + Args: + code: APIが出力するエラーコード(e.g., "invalidParameterValue") + message: エラーメッセージ + response_json: レスポンスの情報が入ったJSONデータ(Optional) + """ + self.code = code + self.message = message + self.response_json = response_json + super().__init__(f"OSC API Error [{code}]: {message}") def _create_payload(name: str, parameters: dict[str, any] | None = None) -> dict[str, any]: @@ -30,10 +48,19 @@ def _create_payload(name: str, parameters: dict[str, any] | None = None) -> dict return {"name":name} return {"name": name, "parameters": parameters} +def set_options(parameters:dict[str, any], timeout:float = 10.0) -> dict[str, any]: + """カメラにオプションを設定します。 -def set_options(parameters:dict[str, any]) -> dict[str, any]: - """ - Thetaへオプションの設定を行う + Args: + parameters (dict[str, any]): Theta Web API v2.1に掲載のオプション名と設定値 + timeout (float, optional): POSTリクエストのタイムアウト時間. Defaults to 10.0. + + Raises: + CameraInternalError: Theta内部でエラーが発生 + CameraTimeout: リクエストのタイムアウト + + Returns: + dict[str, any]: Thetaからのレスポンス """ payload = _create_payload( _Name.SET_OPTIONS, @@ -45,15 +72,30 @@ def set_options(parameters:dict[str, any]) -> dict[str, any]: url=_ThetaConstans.EXECUTE_URL, json=payload, headers=_ThetaConstans.HEADERS, - timeout=10, + timeout=timeout, ) + response.raise_for_status() + data = response.json() + if "error" in data: + err = data["error"] + raise CameraInternalError(err.get("code"), err.get("message"), data) return response.json - except requests.exceptions.Timeout: - return _ThetaWirelessResponse.TIMEOUT + except requests.exceptions.Timeout as e: + raise CameraTimeout("タイムアウトしました") from e -def get_options(option_names:set[str]) -> dict[str, any]: - """ - Thetaに設定したオプションの情報を取得する +def get_options(option_names:set[str], timeout:float = 10.0) -> dict[str, any]: + """カメラの状態を確認します。 + + Args: + option_names (set[str]): Theta Web API v2.1に掲載の確認したいオプション名 + timeout (float, optional): POSTリクエストのタイムアウト時間. Defaults to 10.0. + + Raises: + CameraInternalError: Theta内部でエラーが発生 + CameraTimeout: リクエストのタイムアウト + + Returns: + dict[str, any]: Thetaからのレスポンス """ payload = _create_payload( _Name.GET_OPTIONS, @@ -65,26 +107,44 @@ def get_options(option_names:set[str]) -> dict[str, any]: url=_ThetaConstans.EXECUTE_URL, json=payload, headers=_ThetaConstans.HEADERS, - timeout=10 + timeout=timeout ) + response.raise_for_status() + data = response.json() + if "error" in data: + err = data["error"] + raise CameraInternalError(err.get("code"), err.get("message"), data) return response.json - except requests.exceptions.Timeout: - return _ThetaWirelessResponse.TIMEOUT + except requests.exceptions.Timeout as e: + raise CameraTimeout("タイムアウトしました") from e +def take_picture(timeout:float=10.0) -> dict[str, any]: + """カメラで撮影します。 -def take_picture() -> dict[str, any]: - """ - Theta Web APIを用いて撮影 + Args: + timeout (float, optional): POSTリクエストのタイムアウト時間. Defaults to 10.0. + + Raises: + CameraInternalError: Theta内部でエラーが発生 + CameraTimeout: リクエストのタイムアウト + + Returns: + dict[str, any]: Thetaからのレスポンス """ - payload = _create_payload( - _Name.TAKE_PICTURE - ) + payload = _create_payload(_Name.TAKE_PICTURE) - response = requests.post( - _ThetaConstans.EXECUTE_URL, - json=payload, - headers=_ThetaConstans.HEADERS, - timeout=10 - ) - response.raise_for_status() - return response.json() + try: + response = requests.post( + _ThetaConstans.EXECUTE_URL, + json=payload, + headers=_ThetaConstans.HEADERS, + timeout=timeout + ) + response.raise_for_status() + data = response.json() + if "error" in data: + err = data["error"] + raise CameraInternalError(err.get("code"), err.get("message"), data) + return response.json() + except requests.exceptions.Timeout as e: + raise CameraTimeout("タイムアウトしました") from e From ecad99857938887821e3c101dff59e3ce043e3d8 Mon Sep 17 00:00:00 2001 From: Sano Chihiro Date: Sun, 7 Sep 2025 01:49:15 +0900 Subject: [PATCH 10/31] =?UTF-8?q?[Update]Theta=E3=81=AB=E8=A8=AD=E5=AE=9A?= =?UTF-8?q?=E3=81=A7=E3=81=8D=E3=82=8BOption=E3=82=92=E5=AE=9A=E6=95=B0?= =?UTF-8?q?=E3=81=A8=E3=81=97=E3=81=A6=E7=99=BB=E9=8C=B2?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- theta_wireless.py | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/theta_wireless.py b/theta_wireless.py index 093c775..818dd3c 100644 --- a/theta_wireless.py +++ b/theta_wireless.py @@ -21,6 +21,15 @@ class _Parameter(str, Enum): OPTIONS = "options" OPTION_NAMES = "optionNames" +class Options(str, Enum): + CAPTURE_MODE = "captureMode" + EXPOSURE_PROGRAM = "exposureProgram" + SLEEP_DELAY = "sleepDelay" + ISO = "iso" + SHUTTER_SPEED = "shutterSpeed" + COLOR_TEMPERATURE = "_colorTemperature" #Theta API only + SHUTTER_VOLUME = "_shutterVolume" #Theta API only + class CameraError(Exception): """全てのカメラ関連エラーの基底クラス""" From 7771fc043d0cf75e49aba664d51b21fc55edb84b Mon Sep 17 00:00:00 2001 From: Sano Chihiro Date: Sun, 7 Sep 2025 01:49:37 +0900 Subject: [PATCH 11/31] =?UTF-8?q?[Update]=E5=88=9D=E6=9C=9F=E5=8C=96?= =?UTF-8?q?=E5=87=A6=E7=90=86=E3=82=92=E9=96=A2=E6=95=B0=E3=82=92=E4=BD=BF?= =?UTF-8?q?=E3=81=A3=E3=81=A6=E6=9B=B8=E3=81=8D=E7=9B=B4=E3=81=97?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- theta_init.py | 44 +++++++++++++++++++++++++------------------- 1 file changed, 25 insertions(+), 19 deletions(-) diff --git a/theta_init.py b/theta_init.py index 28fd9e6..92b81e9 100755 --- a/theta_init.py +++ b/theta_init.py @@ -1,24 +1,30 @@ -"""Script for controlling RICOH THETA camera.""" +"""Thetaカメラを初期化します""" -import requests +import theta_wireless +from theta_wireless import Options -# pylint: disable=duplicate-code +try: + theta_wireless.set_options( + { + Options.CAPTURE_MODE:"image", + Options.EXPOSURE_PROGRAM:1, + Options.SLEEP_DELAY:65535, + Options.SHUTTER_VOLUME:0 + } + ) + response = theta_wireless.get_options( + { + Options.CAPTURE_MODE, + Options.EXPOSURE_PROGRAM, + Options.SLEEP_DELAY, + Options.SHUTTER_VOLUME + } + ) + print(response.json()) -URL = "http://192.168.1.1/osc/commands/execute" -HEADERS = {"Content-Type": "application/json;charset=utf-8"} +except theta_wireless.CameraInternalError as e: + print(f"Caught OSC API error: {e.code} -> {e.message}") -payload = { - "name": "camera.setOptions", - "parameters": {"options": {"captureMode": "image"}}, -} +except theta_wireless.CameraTimeout as e: + print("Timeoutしました") -resp = requests.post(URL, json=payload, headers=HEADERS, timeout=10) -print(resp.json()) - -payload = { - "name": "camera.setOptions", - "parameters": {"options": {"exposureProgram": 1}}, -} - -resp = requests.post(URL, json=payload, headers=HEADERS, timeout=10) -print(resp.json()) From bdb59f41b4f150fa63000e1c0185beecd4cb21ed Mon Sep 17 00:00:00 2001 From: Sano Chihiro Date: Sun, 7 Sep 2025 02:14:14 +0900 Subject: [PATCH 12/31] =?UTF-8?q?[delete]=E3=82=B9=E3=83=86=E3=83=BC?= =?UTF-8?q?=E3=82=BF=E3=82=B9=E7=A2=BA=E8=AA=8D=E3=82=B3=E3=83=BC=E3=83=89?= =?UTF-8?q?=E3=82=92=E5=89=8A=E9=99=A4?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- theta_status.py | 19 ------------------- 1 file changed, 19 deletions(-) delete mode 100755 theta_status.py diff --git a/theta_status.py b/theta_status.py deleted file mode 100755 index 08a1060..0000000 --- a/theta_status.py +++ /dev/null @@ -1,19 +0,0 @@ -"""Script for controlling RICOH THETA camera.""" - -import requests - -# pylint: disable=duplicate-code - -URL = "http://192.168.1.1/osc/commands/execute" -HEADERS = {"Content-Type": "application/json;charset=utf-8"} - -# 確認したいオプションを parameters に必ず入れる -payload = { - "name": "camera.getOptions", - "parameters": { - "optionNames": ["iso", "shutterSpeed", "aperture", "_colorTemperature"] - }, -} - -resp = requests.post(URL, json=payload, headers=HEADERS, timeout=10) -print(resp.json()) From d853ce88001ac8205a4b1f97c48f842f5f54008f Mon Sep 17 00:00:00 2001 From: Sano Chihiro Date: Sun, 7 Sep 2025 02:15:05 +0900 Subject: [PATCH 13/31] =?UTF-8?q?[Update]=E3=82=AA=E3=83=97=E3=82=B7?= =?UTF-8?q?=E3=83=A7=E3=83=B3=E3=81=AEEnum=E3=81=AB=E3=83=9B=E3=83=AF?= =?UTF-8?q?=E3=82=A4=E3=83=88=E3=83=90=E3=83=A9=E3=83=B3=E3=82=B9=E3=82=92?= =?UTF-8?q?=E8=BF=BD=E5=8A=A0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- theta_wireless.py | 1 + 1 file changed, 1 insertion(+) diff --git a/theta_wireless.py b/theta_wireless.py index 818dd3c..cdaffad 100644 --- a/theta_wireless.py +++ b/theta_wireless.py @@ -27,6 +27,7 @@ class Options(str, Enum): SLEEP_DELAY = "sleepDelay" ISO = "iso" SHUTTER_SPEED = "shutterSpeed" + WHITE_BALANCE = "whiteBalance" COLOR_TEMPERATURE = "_colorTemperature" #Theta API only SHUTTER_VOLUME = "_shutterVolume" #Theta API only From 44ae730f53191ca6eec3a29365fb9b03f6f9ce59 Mon Sep 17 00:00:00 2001 From: Sano Chihiro Date: Sun, 7 Sep 2025 02:25:24 +0900 Subject: [PATCH 14/31] =?UTF-8?q?[Update]=E3=82=B9=E3=83=86=E3=83=BC?= =?UTF-8?q?=E3=82=BF=E3=82=B9=E3=81=AE=E7=A2=BA=E8=AA=8D=E3=82=B3=E3=83=BC?= =?UTF-8?q?=E3=83=89=E3=82=92=E8=BF=BD=E5=8A=A0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- theta_wireless.py | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/theta_wireless.py b/theta_wireless.py index cdaffad..5d7e399 100644 --- a/theta_wireless.py +++ b/theta_wireless.py @@ -158,3 +158,21 @@ def take_picture(timeout:float=10.0) -> dict[str, any]: return response.json() except requests.exceptions.Timeout as e: raise CameraTimeout("タイムアウトしました") from e + + +def check_status(command_id, timeout:float=10.0) -> dict[str, any]: + try: + response = requests.post( + _ThetaConstans.STATUS_URL, + json={"id":command_id}, + headers=_ThetaConstans.HEADERS, + timeout=timeout + ) + response.raise_for_status() + data = response.json() + if "error" in data: + err = data["error"] + raise CameraInternalError(err.get("code"), err.get("message"), data) + return response.json() + except requests.exceptions.Timeout as e: + raise CameraTimeout("タイムアウトしました") from e From 5b530f65c7dadb73146be0624eee873d0eb2cc3a Mon Sep 17 00:00:00 2001 From: Sano Chihiro Date: Sun, 7 Sep 2025 02:25:57 +0900 Subject: [PATCH 15/31] =?UTF-8?q?[Update]=E3=83=86=E3=82=B9=E3=83=88?= =?UTF-8?q?=E3=82=AD=E3=83=A3=E3=83=97=E3=83=81=E3=83=A3=E3=82=B3=E3=83=BC?= =?UTF-8?q?=E3=83=89=E3=82=92=E9=96=A2=E6=95=B0=E3=82=92=E4=BD=BF=E3=81=A3?= =?UTF-8?q?=E3=81=A6=E8=A8=98=E8=BF=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- theta_test_capture.py | 54 +++++++++++++++---------------------------- 1 file changed, 19 insertions(+), 35 deletions(-) diff --git a/theta_test_capture.py b/theta_test_capture.py index d264817..8249e7c 100755 --- a/theta_test_capture.py +++ b/theta_test_capture.py @@ -2,16 +2,9 @@ import time -import requests +import theta_wireless as tw +from theta_wireless import Options -# pylint: disable=duplicate-code - -# カメラIP -THETA_IP = "192.168.1.1" -EXECUTE_URL = f"http://{THETA_IP}/osc/commands/execute" -STATUS_URL = f"http://{THETA_IP}/osc/commands/status" - -HEADERS = {"Content-Type": "application/json;charset=utf-8"} # 撮影設定リスト (ISO, shutter_speed, f, ColorTemperature) settings_list = [ @@ -32,37 +25,28 @@ def set_options(iso, shutter_speed, white_balance): """オプションを設定""" - options_command = { - "name": "camera.setOptions", - "parameters": { - "options": { - "iso": iso, - "shutterSpeed": shutter_speed, - "_colorTemperature": white_balance, - } - }, - } - resp = requests.post(EXECUTE_URL, json=options_command, headers=HEADERS, timeout=10) - resp.raise_for_status() - return resp.json() - - -def take_picture(): - """Take a picture using the Theta API""" - take_command = {"name": "camera.takePicture"} - resp = requests.post(EXECUTE_URL, json=take_command, headers=HEADERS, timeout=10) - resp.raise_for_status() + tw.set_options( + { + Options.ISO:iso, + Options.SHUTTER_SPEED: shutter_speed, + Options.WHITE_BALANCE: Options.COLOR_TEMPERATURE, + Options.COLOR_TEMPERATURE: white_balance + } + ) + resp = tw.get_options( + { + Options.ISO, + Options.SHUTTER_SPEED, + Options.COLOR_TEMPERATURE + } + ) return resp.json() def wait_for_completion(command_id): """Wait a few seconds to complete""" while True: - status_resp = requests.post( - STATUS_URL, json={"id": command_id}, headers=HEADERS, timeout=10 - ) - status_resp.raise_for_status() - status = status_resp.json() + status = tw.check_status(command_id=command_id) if status.get("state") == "done": return status.get("results") time.sleep(0.5) @@ -74,7 +58,7 @@ def wait_for_completion(command_id): set_options(**s) print("設定完了:", s) - result = take_picture() + result = tw.take_picture() print("撮影コマンド送信:", result) if "id" in result: From 803e7e4950ec434bf773f402525e2e6e9826e973 Mon Sep 17 00:00:00 2001 From: Sano Chihiro Date: Sun, 7 Sep 2025 02:54:30 +0900 Subject: [PATCH 16/31] =?UTF-8?q?[Fix]=E3=83=AA=E3=83=B3=E3=83=88=E3=82=A8?= =?UTF-8?q?=E3=83=A9=E3=83=BC=E4=BF=AE=E6=AD=A3?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- theta_wireless.py | 33 +++++++++++++++++++++++---------- 1 file changed, 23 insertions(+), 10 deletions(-) diff --git a/theta_wireless.py b/theta_wireless.py index 5d7e399..9fb1862 100644 --- a/theta_wireless.py +++ b/theta_wireless.py @@ -31,7 +31,7 @@ class Options(str, Enum): COLOR_TEMPERATURE = "_colorTemperature" #Theta API only SHUTTER_VOLUME = "_shutterVolume" #Theta API only -class CameraError(Exception): +class CameraError(Exception): """全てのカメラ関連エラーの基底クラス""" class CameraTimeout(CameraError): @@ -54,7 +54,7 @@ def __init__(self, code:str, message:str, response_json:dict[str,any]=None): def _create_payload(name: str, parameters: dict[str, any] | None = None) -> dict[str, any]: - if (dict is None): + if dict is None: return {"name":name} return {"name": name, "parameters": parameters} @@ -145,9 +145,9 @@ def take_picture(timeout:float=10.0) -> dict[str, any]: try: response = requests.post( - _ThetaConstans.EXECUTE_URL, - json=payload, - headers=_ThetaConstans.HEADERS, + _ThetaConstans.EXECUTE_URL, + json=payload, + headers=_ThetaConstans.HEADERS, timeout=timeout ) response.raise_for_status() @@ -158,14 +158,27 @@ def take_picture(timeout:float=10.0) -> dict[str, any]: return response.json() except requests.exceptions.Timeout as e: raise CameraTimeout("タイムアウトしました") from e - -def check_status(command_id, timeout:float=10.0) -> dict[str, any]: + +def check_status(command_id:str, timeout:float=10.0) -> dict[str, any]: + """コマンドのステータスをチェックします。 + + Args: + command_id (str): コマンドのID + timeout (float, optional): POSTリクエストのタイムアウト時間. Defaults to 10.0. + + Raises: + CameraInternalError: Theta内部でエラーが発生 + CameraTimeout: リクエストのタイムアウト + + Returns: + dict[str, any]: Thetaからのレスポンス + """ try: response = requests.post( - _ThetaConstans.STATUS_URL, - json={"id":command_id}, - headers=_ThetaConstans.HEADERS, + _ThetaConstans.STATUS_URL, + json={"id":command_id}, + headers=_ThetaConstans.HEADERS, timeout=timeout ) response.raise_for_status() From 1eace129b0d50ad03ce55657ee386c3ec055a012 Mon Sep 17 00:00:00 2001 From: Sano Chihiro Date: Sun, 7 Sep 2025 02:59:04 +0900 Subject: [PATCH 17/31] =?UTF-8?q?[Update]=E5=85=B1=E9=80=9A=E3=81=99?= =?UTF-8?q?=E3=82=8B=E3=82=B3=E3=83=BC=E3=83=89=E3=83=95=E3=83=A9=E3=82=B0?= =?UTF-8?q?=E3=83=A1=E3=83=B3=E3=83=88=E3=82=92=E9=96=A2=E6=95=B0=E5=8C=96?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- theta_wireless.py | 101 +++++++++++++++++----------------------------- 1 file changed, 37 insertions(+), 64 deletions(-) diff --git a/theta_wireless.py b/theta_wireless.py index 9fb1862..7ce3096 100644 --- a/theta_wireless.py +++ b/theta_wireless.py @@ -58,6 +58,23 @@ def _create_payload(name: str, parameters: dict[str, any] | None = None) -> dict return {"name":name} return {"name": name, "parameters": parameters} +def _send_request_and_error_handle(url:_ThetaConstans, payload:dict[str, any], timeout:float) -> dict[str, any]: + try: + response = requests.post( + url=url, + json=payload, + headers=_ThetaConstans.HEADERS, + timeout=timeout, + ) + response.raise_for_status() + data = response.json() + if "error" in data: + err = data["error"] + raise CameraInternalError(err.get("code"), err.get("message"), data) + return response.json + except requests.exceptions.Timeout as e: + raise CameraTimeout("タイムアウトしました") from e + def set_options(parameters:dict[str, any], timeout:float = 10.0) -> dict[str, any]: """カメラにオプションを設定します。 @@ -76,22 +93,11 @@ def set_options(parameters:dict[str, any], timeout:float = 10.0) -> dict[str, an _Name.SET_OPTIONS, {_Parameter.OPTIONS: parameters}, ) - - try: - response = requests.post( - url=_ThetaConstans.EXECUTE_URL, - json=payload, - headers=_ThetaConstans.HEADERS, - timeout=timeout, - ) - response.raise_for_status() - data = response.json() - if "error" in data: - err = data["error"] - raise CameraInternalError(err.get("code"), err.get("message"), data) - return response.json - except requests.exceptions.Timeout as e: - raise CameraTimeout("タイムアウトしました") from e + _send_request_and_error_handle( + _ThetaConstans.EXECUTE_URL, + payload=payload, + timeout=timeout + ) def get_options(option_names:set[str], timeout:float = 10.0) -> dict[str, any]: """カメラの状態を確認します。 @@ -111,22 +117,11 @@ def get_options(option_names:set[str], timeout:float = 10.0) -> dict[str, any]: _Name.GET_OPTIONS, {_Parameter.OPTION_NAMES:option_names} ) - - try: - response = requests.post( - url=_ThetaConstans.EXECUTE_URL, - json=payload, - headers=_ThetaConstans.HEADERS, - timeout=timeout - ) - response.raise_for_status() - data = response.json() - if "error" in data: - err = data["error"] - raise CameraInternalError(err.get("code"), err.get("message"), data) - return response.json - except requests.exceptions.Timeout as e: - raise CameraTimeout("タイムアウトしました") from e + _send_request_and_error_handle( + _ThetaConstans.EXECUTE_URL, + payload=payload, + timeout=timeout + ) def take_picture(timeout:float=10.0) -> dict[str, any]: """カメラで撮影します。 @@ -142,23 +137,11 @@ def take_picture(timeout:float=10.0) -> dict[str, any]: dict[str, any]: Thetaからのレスポンス """ payload = _create_payload(_Name.TAKE_PICTURE) - - try: - response = requests.post( - _ThetaConstans.EXECUTE_URL, - json=payload, - headers=_ThetaConstans.HEADERS, - timeout=timeout - ) - response.raise_for_status() - data = response.json() - if "error" in data: - err = data["error"] - raise CameraInternalError(err.get("code"), err.get("message"), data) - return response.json() - except requests.exceptions.Timeout as e: - raise CameraTimeout("タイムアウトしました") from e - + _send_request_and_error_handle( + _ThetaConstans.EXECUTE_URL, + payload=payload, + timeout=timeout + ) def check_status(command_id:str, timeout:float=10.0) -> dict[str, any]: """コマンドのステータスをチェックします。 @@ -174,18 +157,8 @@ def check_status(command_id:str, timeout:float=10.0) -> dict[str, any]: Returns: dict[str, any]: Thetaからのレスポンス """ - try: - response = requests.post( - _ThetaConstans.STATUS_URL, - json={"id":command_id}, - headers=_ThetaConstans.HEADERS, - timeout=timeout - ) - response.raise_for_status() - data = response.json() - if "error" in data: - err = data["error"] - raise CameraInternalError(err.get("code"), err.get("message"), data) - return response.json() - except requests.exceptions.Timeout as e: - raise CameraTimeout("タイムアウトしました") from e + _send_request_and_error_handle( + _ThetaConstans.STATUS_URL, + payload={"id":command_id}, + timeout=timeout + ) From 23ed28dd05ffcf1152591a76ac00c85371577c5b Mon Sep 17 00:00:00 2001 From: Sano Chihiro Date: Sun, 7 Sep 2025 03:04:20 +0900 Subject: [PATCH 18/31] =?UTF-8?q?[Fix]=E3=83=90=E3=82=B0=E3=81=AE=E4=BF=AE?= =?UTF-8?q?=E6=AD=A3?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- theta_init.py | 2 +- theta_wireless.py | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/theta_init.py b/theta_init.py index 92b81e9..c760e3e 100755 --- a/theta_init.py +++ b/theta_init.py @@ -20,7 +20,7 @@ Options.SHUTTER_VOLUME } ) - print(response.json()) + print(response) except theta_wireless.CameraInternalError as e: print(f"Caught OSC API error: {e.code} -> {e.message}") diff --git a/theta_wireless.py b/theta_wireless.py index 7ce3096..27caf75 100644 --- a/theta_wireless.py +++ b/theta_wireless.py @@ -71,7 +71,7 @@ def _send_request_and_error_handle(url:_ThetaConstans, payload:dict[str, any], t if "error" in data: err = data["error"] raise CameraInternalError(err.get("code"), err.get("message"), data) - return response.json + return response.json() except requests.exceptions.Timeout as e: raise CameraTimeout("タイムアウトしました") from e From 96eff6547f83b53c62d63f762f59d21d690a3364 Mon Sep 17 00:00:00 2001 From: Sano Chihiro Date: Sun, 7 Sep 2025 03:09:37 +0900 Subject: [PATCH 19/31] =?UTF-8?q?[Fix]update=E3=81=97=E3=81=A6=E3=81=84?= =?UTF-8?q?=E3=81=AA=E3=81=84=E7=AE=87=E6=89=80=E3=82=92=E4=BF=AE=E6=AD=A3?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- theta_wireless.py | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/theta_wireless.py b/theta_wireless.py index 27caf75..aff0687 100644 --- a/theta_wireless.py +++ b/theta_wireless.py @@ -93,11 +93,12 @@ def set_options(parameters:dict[str, any], timeout:float = 10.0) -> dict[str, an _Name.SET_OPTIONS, {_Parameter.OPTIONS: parameters}, ) - _send_request_and_error_handle( + response_json = _send_request_and_error_handle( _ThetaConstans.EXECUTE_URL, payload=payload, timeout=timeout ) + return response_json def get_options(option_names:set[str], timeout:float = 10.0) -> dict[str, any]: """カメラの状態を確認します。 @@ -117,11 +118,12 @@ def get_options(option_names:set[str], timeout:float = 10.0) -> dict[str, any]: _Name.GET_OPTIONS, {_Parameter.OPTION_NAMES:option_names} ) - _send_request_and_error_handle( + response_json = _send_request_and_error_handle( _ThetaConstans.EXECUTE_URL, payload=payload, timeout=timeout ) + return response_json def take_picture(timeout:float=10.0) -> dict[str, any]: """カメラで撮影します。 @@ -137,11 +139,12 @@ def take_picture(timeout:float=10.0) -> dict[str, any]: dict[str, any]: Thetaからのレスポンス """ payload = _create_payload(_Name.TAKE_PICTURE) - _send_request_and_error_handle( + response_json = _send_request_and_error_handle( _ThetaConstans.EXECUTE_URL, payload=payload, timeout=timeout ) + return response_json def check_status(command_id:str, timeout:float=10.0) -> dict[str, any]: """コマンドのステータスをチェックします。 @@ -157,8 +160,9 @@ def check_status(command_id:str, timeout:float=10.0) -> dict[str, any]: Returns: dict[str, any]: Thetaからのレスポンス """ - _send_request_and_error_handle( + response_json = _send_request_and_error_handle( _ThetaConstans.STATUS_URL, payload={"id":command_id}, timeout=timeout ) + return response_json From 7bbe5e4ee6f42da6835577f0e1b28da06434e562 Mon Sep 17 00:00:00 2001 From: Sano Chihiro Date: Sun, 7 Sep 2025 03:09:48 +0900 Subject: [PATCH 20/31] =?UTF-8?q?[Fix]=E6=94=B9=E8=A1=8C=E3=82=92=E5=89=8A?= =?UTF-8?q?=E9=99=A4?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- theta_init.py | 1 - 1 file changed, 1 deletion(-) diff --git a/theta_init.py b/theta_init.py index c760e3e..dc9e925 100755 --- a/theta_init.py +++ b/theta_init.py @@ -27,4 +27,3 @@ except theta_wireless.CameraTimeout as e: print("Timeoutしました") - From 51c1ff6df10d8d3c5ff13b3c0816341b8fe2b7ef Mon Sep 17 00:00:00 2001 From: Sano Chihiro Date: Sun, 7 Sep 2025 03:12:39 +0900 Subject: [PATCH 21/31] =?UTF-8?q?[Fix]docstring=E3=81=AE=E8=BF=BD=E5=8A=A0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- theta_wireless.py | 1 + 1 file changed, 1 insertion(+) diff --git a/theta_wireless.py b/theta_wireless.py index aff0687..24944f7 100644 --- a/theta_wireless.py +++ b/theta_wireless.py @@ -22,6 +22,7 @@ class _Parameter(str, Enum): OPTION_NAMES = "optionNames" class Options(str, Enum): + """Thetaに指定できるOptionsのうち輝度画像合成に必要なもの""" CAPTURE_MODE = "captureMode" EXPOSURE_PROGRAM = "exposureProgram" SLEEP_DELAY = "sleepDelay" From 380785af992e46d0b51682b20b58900d9cd8f191 Mon Sep 17 00:00:00 2001 From: Sano Chihiro Date: Sun, 7 Sep 2025 03:12:56 +0900 Subject: [PATCH 22/31] =?UTF-8?q?[Fix]=E9=95=B7=E3=81=84=E8=A1=8C=E3=82=92?= =?UTF-8?q?=E6=94=B9=E8=A1=8C?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- theta_wireless.py | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/theta_wireless.py b/theta_wireless.py index 24944f7..933e5dd 100644 --- a/theta_wireless.py +++ b/theta_wireless.py @@ -59,7 +59,11 @@ def _create_payload(name: str, parameters: dict[str, any] | None = None) -> dict return {"name":name} return {"name": name, "parameters": parameters} -def _send_request_and_error_handle(url:_ThetaConstans, payload:dict[str, any], timeout:float) -> dict[str, any]: +def _send_request_and_error_handle( + url:_ThetaConstans, + payload:dict[str, any], + timeout:float + ) -> dict[str, any]: try: response = requests.post( url=url, From 6ce5ee2e324040ed7b9995b4e7b769497e31d541 Mon Sep 17 00:00:00 2001 From: Sano Chihiro Date: Sun, 7 Sep 2025 03:17:40 +0900 Subject: [PATCH 23/31] =?UTF-8?q?[Fix]=E5=9E=8B=E3=81=8C=E9=96=93=E9=81=95?= =?UTF-8?q?=E3=81=A3=E3=81=A6=E3=81=84=E3=82=8B=E7=AE=87=E6=89=80=E3=82=92?= =?UTF-8?q?=E4=BF=AE=E6=AD=A3?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- theta_test_capture.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/theta_test_capture.py b/theta_test_capture.py index 8249e7c..a25e0bf 100755 --- a/theta_test_capture.py +++ b/theta_test_capture.py @@ -40,7 +40,7 @@ def set_options(iso, shutter_speed, white_balance): Options.COLOR_TEMPERATURE } ) - return resp.json() + return resp def wait_for_completion(command_id): From 8d83250af561ac1d0d5e3b74c4b71e76bd2145c2 Mon Sep 17 00:00:00 2001 From: Sano Chihiro Date: Sun, 7 Sep 2025 03:28:32 +0900 Subject: [PATCH 24/31] =?UTF-8?q?[Fix]=E9=96=A2=E6=95=B0=E3=81=AE=E5=91=BD?= =?UTF-8?q?=E5=90=8D=E3=82=92=E5=A4=89=E6=9B=B4?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- theta_wireless.py | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/theta_wireless.py b/theta_wireless.py index 933e5dd..41c15fe 100644 --- a/theta_wireless.py +++ b/theta_wireless.py @@ -59,7 +59,7 @@ def _create_payload(name: str, parameters: dict[str, any] | None = None) -> dict return {"name":name} return {"name": name, "parameters": parameters} -def _send_request_and_error_handle( +def _send_request( url:_ThetaConstans, payload:dict[str, any], timeout:float @@ -98,7 +98,7 @@ def set_options(parameters:dict[str, any], timeout:float = 10.0) -> dict[str, an _Name.SET_OPTIONS, {_Parameter.OPTIONS: parameters}, ) - response_json = _send_request_and_error_handle( + response_json = _send_request( _ThetaConstans.EXECUTE_URL, payload=payload, timeout=timeout @@ -123,7 +123,7 @@ def get_options(option_names:set[str], timeout:float = 10.0) -> dict[str, any]: _Name.GET_OPTIONS, {_Parameter.OPTION_NAMES:option_names} ) - response_json = _send_request_and_error_handle( + response_json = _send_request( _ThetaConstans.EXECUTE_URL, payload=payload, timeout=timeout @@ -144,7 +144,7 @@ def take_picture(timeout:float=10.0) -> dict[str, any]: dict[str, any]: Thetaからのレスポンス """ payload = _create_payload(_Name.TAKE_PICTURE) - response_json = _send_request_and_error_handle( + response_json = _send_request( _ThetaConstans.EXECUTE_URL, payload=payload, timeout=timeout @@ -165,7 +165,7 @@ def check_status(command_id:str, timeout:float=10.0) -> dict[str, any]: Returns: dict[str, any]: Thetaからのレスポンス """ - response_json = _send_request_and_error_handle( + response_json = _send_request( _ThetaConstans.STATUS_URL, payload={"id":command_id}, timeout=timeout From d2b11f704c2c5595675b5b9a3430bbf390e43bc1 Mon Sep 17 00:00:00 2001 From: Sano Chihiro Date: Tue, 9 Sep 2025 20:07:21 +0900 Subject: [PATCH 25/31] =?UTF-8?q?[Update]theta=5Finit=E3=81=AE=E5=87=A6?= =?UTF-8?q?=E7=90=86=E3=82=92=E9=96=A2=E6=95=B0=E3=81=A8=E3=81=97=E3=81=A6?= =?UTF-8?q?=E5=A4=96=E9=83=A8=E3=81=8B=E3=82=89=E5=8F=82=E7=85=A7=E5=8F=AF?= =?UTF-8?q?=E8=83=BD=E3=81=AB=E5=A4=89=E6=9B=B4?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- theta_init.py | 49 +++++++++++++++++++++++++++---------------------- 1 file changed, 27 insertions(+), 22 deletions(-) diff --git a/theta_init.py b/theta_init.py index dc9e925..f89e096 100755 --- a/theta_init.py +++ b/theta_init.py @@ -3,27 +3,32 @@ import theta_wireless from theta_wireless import Options -try: - theta_wireless.set_options( - { - Options.CAPTURE_MODE:"image", - Options.EXPOSURE_PROGRAM:1, - Options.SLEEP_DELAY:65535, - Options.SHUTTER_VOLUME:0 - } - ) - response = theta_wireless.get_options( - { - Options.CAPTURE_MODE, - Options.EXPOSURE_PROGRAM, - Options.SLEEP_DELAY, - Options.SHUTTER_VOLUME - } - ) - print(response) +def init(): + """Thetaの初期化処理を行います。""" + try: + theta_wireless.set_options( + { + Options.CAPTURE_MODE:"image", + Options.EXPOSURE_PROGRAM:1, + Options.SLEEP_DELAY:65535, + Options.SHUTTER_VOLUME:0 + } + ) + response = theta_wireless.get_options( + { + Options.CAPTURE_MODE, + Options.EXPOSURE_PROGRAM, + Options.SLEEP_DELAY, + Options.SHUTTER_VOLUME + } + ) + print(response) -except theta_wireless.CameraInternalError as e: - print(f"Caught OSC API error: {e.code} -> {e.message}") + except theta_wireless.CameraInternalError as e: + print(f"Caught OSC API error: {e.code} -> {e.message}") -except theta_wireless.CameraTimeout as e: - print("Timeoutしました") + except theta_wireless.CameraTimeout as e: + print("Timeoutしました") + +if __name__ == "__main__": + init() \ No newline at end of file From 854a23d2464a35a1d8675b321ec0180e80985f9c Mon Sep 17 00:00:00 2001 From: Sano Chihiro Date: Tue, 9 Sep 2025 20:07:59 +0900 Subject: [PATCH 26/31] =?UTF-8?q?[Update]=E3=83=86=E3=82=B9=E3=83=88?= =?UTF-8?q?=E7=94=A8=E3=81=AE=E9=96=A2=E6=95=B0=E3=81=ABLinter=E3=81=AE?= =?UTF-8?q?=E3=82=A2=E3=83=8E=E3=83=86=E3=83=BC=E3=82=B7=E3=83=A7=E3=83=B3?= =?UTF-8?q?=E3=82=92=E4=BB=98=E4=B8=8E?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- theta_test_capture.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/theta_test_capture.py b/theta_test_capture.py index a25e0bf..5a2a9bf 100755 --- a/theta_test_capture.py +++ b/theta_test_capture.py @@ -5,6 +5,8 @@ import theta_wireless as tw from theta_wireless import Options +# pylint: disable=duplicate-code + # 撮影設定リスト (ISO, shutter_speed, f, ColorTemperature) settings_list = [ From 58c56f3f21002da50f1b753749f9d20fe243aa46 Mon Sep 17 00:00:00 2001 From: Sano Chihiro Date: Tue, 9 Sep 2025 20:08:12 +0900 Subject: [PATCH 27/31] =?UTF-8?q?[Update]=E9=96=A2=E6=95=B0=E3=82=92?= =?UTF-8?q?=E7=94=A8=E3=81=84=E3=81=A6=E8=A8=98=E8=BF=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- theta_capture.py | 66 ++++++++++++++++++++---------------------------- 1 file changed, 28 insertions(+), 38 deletions(-) diff --git a/theta_capture.py b/theta_capture.py index c2f2305..0a42548 100755 --- a/theta_capture.py +++ b/theta_capture.py @@ -3,16 +3,10 @@ import time import datetime -import requests +import theta_wireless as tw +from theta_wireless import Options +import theta_init -# pylint: disable=duplicate-code - -# カメラIP -THETA_IP = "192.168.1.1" -EXECUTE_URL = f"http://{THETA_IP}/osc/commands/execute" -STATUS_URL = f"http://{THETA_IP}/osc/commands/status" - -HEADERS = {"Content-Type": "application/json;charset=utf-8"} # 撮影設定リスト (ISO, shutter_speed, ColorTemperature) settings_list = [ @@ -33,38 +27,28 @@ def set_options(iso, shutter_speed, white_balance): """オプションを設定""" - options_command = { - "name": "camera.setOptions", - "parameters": { - "options": { - "iso": iso, - "shutterSpeed": shutter_speed, - "whiteBalance": "_colorTemperature", - "colorTemperature": white_balance, - } - }, - } - resp = requests.post(EXECUTE_URL, json=options_command, headers=HEADERS, timeout=10) - resp.raise_for_status() - return resp.json() - - -def take_picture(): - """Theta Web APIを用いて撮影""" - take_command = {"name": "camera.takePicture"} - resp = requests.post(EXECUTE_URL, json=take_command, headers=HEADERS, timeout=10) - resp.raise_for_status() - return resp.json() + tw.set_options( + { + Options.ISO:iso, + Options.SHUTTER_SPEED: shutter_speed, + Options.WHITE_BALANCE: Options.COLOR_TEMPERATURE, + Options.COLOR_TEMPERATURE: white_balance + } + ) + resp = tw.get_options( + { + Options.ISO, + Options.SHUTTER_SPEED, + Options.COLOR_TEMPERATURE + } + ) + return resp def wait_for_completion(command_id): """撮影完了まで処理を停止""" while True: - status_resp = requests.post( - STATUS_URL, json={"id": command_id}, headers=HEADERS, timeout=10 - ) - status_resp.raise_for_status() - status = status_resp.json() + status = tw.check_status(command_id=command_id) if status.get("state") == "done": return status.get("results") time.sleep(0.5) @@ -77,7 +61,7 @@ def capture_12(): set_options(**s) print("設定完了:", s) - result = take_picture() + result = tw.take_picture() print("撮影コマンド送信:", result) if "id" in result: @@ -119,5 +103,11 @@ def schedule_shoots(): time.sleep(wait_sec / 60) -if __name__ == "__main__": +def main(): + """メイン関数""" + theta_init.init() schedule_shoots() + + +if __name__ == "__main__": + main() From 6295342e36b72e2bc99bc5d8a5c0c51ef315cb2c Mon Sep 17 00:00:00 2001 From: Sano Chihiro Date: Tue, 9 Sep 2025 20:10:37 +0900 Subject: [PATCH 28/31] =?UTF-8?q?[Fix]Linter=E3=81=AE=E3=82=A8=E3=83=A9?= =?UTF-8?q?=E3=83=BC=E5=AF=BE=E5=BF=9C?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- theta_init.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/theta_init.py b/theta_init.py index f89e096..f1b913f 100755 --- a/theta_init.py +++ b/theta_init.py @@ -28,7 +28,7 @@ def init(): print(f"Caught OSC API error: {e.code} -> {e.message}") except theta_wireless.CameraTimeout as e: - print("Timeoutしました") + print(f"Timeoutしました: {e}") if __name__ == "__main__": - init() \ No newline at end of file + init() From e81aa24df34b0d990af451a935f121a97b3e0ff9 Mon Sep 17 00:00:00 2001 From: Sano Chihiro Date: Tue, 9 Sep 2025 20:19:33 +0900 Subject: [PATCH 29/31] =?UTF-8?q?[Fix]typo=E4=BF=AE=E6=AD=A3?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- theta_wireless.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/theta_wireless.py b/theta_wireless.py index 41c15fe..3e9f059 100644 --- a/theta_wireless.py +++ b/theta_wireless.py @@ -55,7 +55,7 @@ def __init__(self, code:str, message:str, response_json:dict[str,any]=None): def _create_payload(name: str, parameters: dict[str, any] | None = None) -> dict[str, any]: - if dict is None: + if parameters is None: return {"name":name} return {"name": name, "parameters": parameters} From 56d12d276265f331a82fa06c530333fa34b63924 Mon Sep 17 00:00:00 2001 From: Sano Chihiro Date: Sat, 13 Sep 2025 12:31:01 +0900 Subject: [PATCH 30/31] =?UTF-8?q?[Fix]=E5=AE=9F=E8=A1=8C=E7=92=B0=E5=A2=83?= =?UTF-8?q?=E3=81=AEPython=E3=83=90=E3=83=BC=E3=82=B8=E3=83=A7=E3=83=B3?= =?UTF-8?q?=E3=81=AB=E5=90=88=E3=82=8F=E3=81=9B=E5=A4=89=E6=9B=B4?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .github/workflows/pylint.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/pylint.yml b/.github/workflows/pylint.yml index 723c664..600eef8 100644 --- a/.github/workflows/pylint.yml +++ b/.github/workflows/pylint.yml @@ -7,7 +7,7 @@ jobs: runs-on: ubuntu-latest strategy: matrix: - python-version: ["3.13"] + python-version: ["3.9"] steps: - uses: actions/checkout@v4 - name: Set up Python ${{ matrix.python-version }} From 7f5138cf0c0a79486ecbd668658484d20ab4894d Mon Sep 17 00:00:00 2001 From: Sano Chihiro Date: Sat, 13 Sep 2025 12:35:26 +0900 Subject: [PATCH 31/31] =?UTF-8?q?[Fix]=E5=9E=8B=E3=83=92=E3=83=B3=E3=83=88?= =?UTF-8?q?=E3=81=AE=E6=9B=B8=E3=81=8D=E6=96=B9=E3=82=92=E4=BF=AE=E6=AD=A3?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- theta_wireless.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/theta_wireless.py b/theta_wireless.py index 3e9f059..d9f33be 100644 --- a/theta_wireless.py +++ b/theta_wireless.py @@ -1,6 +1,7 @@ """Theta Web APIを利用した関数""" from enum import Enum +from typing import Optional import requests @@ -54,7 +55,7 @@ def __init__(self, code:str, message:str, response_json:dict[str,any]=None): super().__init__(f"OSC API Error [{code}]: {message}") -def _create_payload(name: str, parameters: dict[str, any] | None = None) -> dict[str, any]: +def _create_payload(name: str, parameters: Optional[dict[str, any]] = None) -> dict[str, any]: if parameters is None: return {"name":name} return {"name": name, "parameters": parameters}