From c78b1c770a572daed192a3547228e13bf15e7463 Mon Sep 17 00:00:00 2001 From: Tim Camise Date: Fri, 6 Sep 2024 12:25:37 -0700 Subject: [PATCH] Add Hero13 settings and statuses (#589) --- .../open_gopro/api/ble_commands.py | 68 +++++++- .../open_gopro/api/http_commands.py | 56 +++++++ .../open_gopro/api/params.py | 153 +++++++++++++++++- .../open_gopro/constants.py | 45 +++++- .../demos/custom_preset_udpate_demo.py | 64 -------- .../open_gopro/demos/video.py | 6 +- 6 files changed, 318 insertions(+), 74 deletions(-) delete mode 100644 demos/python/sdk_wireless_camera_control/open_gopro/demos/custom_preset_udpate_demo.py diff --git a/demos/python/sdk_wireless_camera_control/open_gopro/api/ble_commands.py b/demos/python/sdk_wireless_camera_control/open_gopro/api/ble_commands.py index 55709526..b696b08f 100644 --- a/demos/python/sdk_wireless_camera_control/open_gopro/api/ble_commands.py +++ b/demos/python/sdk_wireless_camera_control/open_gopro/api/ble_commands.py @@ -1072,8 +1072,6 @@ def __init__(self, communicator: GoProBle): ) """Interval between photo captures""" - super().__init__(communicator) - self.photo_output: BleSetting[Params.PhotoOutput] = BleSetting[Params.PhotoOutput]( communicator, SettingId.PHOTO_OUTPUT, @@ -1086,6 +1084,62 @@ def __init__(self, communicator: GoProBle): ) """If set, a video will automatically be stopped after recording for this long.""" + self.regional_format: BleSetting[Params.RegionalFormat] = BleSetting[Params.RegionalFormat]( + communicator, SettingId.REGIONAL_FORMAT, Params.RegionalFormat + ) + + self.quality_control: BleSetting[Params.QualityControl] = BleSetting[Params.QualityControl]( + communicator, SettingId.QUALITY_CONTROL, Params.QualityControl + ) + + self.camera_volume: BleSetting[Params.Volume] = BleSetting[Params.Volume]( + communicator, SettingId.CAMERA_VOLUME, Params.Volume + ) + + self.lens_attachment: BleSetting[Params.LensAttachment] = BleSetting[Params.LensAttachment]( + communicator, SettingId.LENS_ATTACHMENT, Params.LensAttachment + ) + + self.setup_screensaver: BleSetting[Params.ScreenSaverTimeout] = BleSetting[Params.ScreenSaverTimeout]( + communicator, SettingId.SETUP_SCREEN_SAVER, Params.ScreenSaverTimeout + ) + + self.setup_language: BleSetting[Params.SetupLanguage] = BleSetting[Params.SetupLanguage]( + communicator, SettingId.SETUP_LANGUAGE, Params.SetupLanguage + ) + + self.auto_power_off: BleSetting[Params.AutoPowerOff] = BleSetting[Params.AutoPowerOff]( + communicator, SettingId.AUTO_POWER_OFF, Params.AutoPowerOff + ) + + self.photo_mode_v2: BleSetting[Params.PhotoModeV2] = BleSetting[Params.PhotoModeV2]( + communicator, SettingId.PHOTO_MODE_V2, Params.PhotoModeV2 + ) + + self.video_digital_lens_v2: BleSetting[Params.VideoLensV2] = BleSetting[Params.VideoLensV2]( + communicator, SettingId.VIDEO_DIGITAL_LENSES_V2, Params.VideoLensV2 + ) + + self.photo_digital_lens_v2: BleSetting[Params.PhotoLensV2] = BleSetting[Params.PhotoLensV2]( + communicator, SettingId.PHOTO_DIGITAL_LENSES_V2, Params.PhotoLensV2 + ) + + self.timelapse_digital_lens_v2: BleSetting[Params.TimelapseLensV2] = BleSetting[Params.TimelapseLensV2]( + communicator, SettingId.TIMELAPSE_DIGITAL_LENSES_V2, Params.TimelapseLensV2 + ) + + self.video_framing: BleSetting[Params.VideoFraming] = BleSetting[Params.VideoFraming]( + communicator, SettingId.VIDEO_FRAMING, Params.VideoFraming + ) + + self.multi_shot_framing: BleSetting[Params.MultishotFraming] = BleSetting[Params.MultishotFraming]( + communicator, SettingId.MULTI_SHOT_FRAMING, Params.MultishotFraming + ) + + self.frame_rate: BleSetting[Params.FrameRate] = BleSetting[Params.FrameRate]( + communicator, SettingId.FRAME_RATE, Params.FrameRate + ) + super().__init__(communicator) @@ -1455,4 +1509,14 @@ def __init__(self, communicator: GoProBle) -> None: self.total_sd_space_kb: BleStatus[int] = BleStatus(communicator, StatusId.TOTAL_SD_SPACE_KB, Int32ub) """Total space taken up on the SD card in kilobytes""" + self.photo_interval_capture_count: BleStatus[int] = BleStatus( + communicator, StatusId.PHOTO_INTERVAL_CAPTURE_COUNT, Int32ub + ) + """Photo interval capture count""" + + self.camera_lens_mod: BleStatus[Params.LensModStatus] = BleStatus( + communicator, StatusId.CAMERA_LENS_MOD, Params.LensModStatus + ) + """Current camera lens mod""" + super().__init__(communicator) diff --git a/demos/python/sdk_wireless_camera_control/open_gopro/api/http_commands.py b/demos/python/sdk_wireless_camera_control/open_gopro/api/http_commands.py index bfbd940e..e6184bd4 100644 --- a/demos/python/sdk_wireless_camera_control/open_gopro/api/http_commands.py +++ b/demos/python/sdk_wireless_camera_control/open_gopro/api/http_commands.py @@ -738,4 +738,60 @@ def __init__(self, communicator: GoProHttp): ) """If set, a video will automatically be stopped after recording for this long.""" + self.regional_format: HttpSetting[Params.RegionalFormat] = HttpSetting[Params.RegionalFormat]( + communicator, SettingId.REGIONAL_FORMAT + ) + + self.quality_control: HttpSetting[Params.QualityControl] = HttpSetting[Params.QualityControl]( + communicator, SettingId.QUALITY_CONTROL + ) + + self.camera_volume: HttpSetting[Params.Volume] = HttpSetting[Params.Volume]( + communicator, SettingId.CAMERA_VOLUME + ) + + self.lens_attachment: HttpSetting[Params.LensAttachment] = HttpSetting[Params.LensAttachment]( + communicator, SettingId.LENS_ATTACHMENT + ) + + self.setup_screensaver: HttpSetting[Params.ScreenSaverTimeout] = HttpSetting[Params.ScreenSaverTimeout]( + communicator, SettingId.SETUP_SCREEN_SAVER + ) + + self.setup_language: HttpSetting[Params.SetupLanguage] = HttpSetting[Params.SetupLanguage]( + communicator, SettingId.SETUP_LANGUAGE + ) + + self.auto_power_off: HttpSetting[Params.AutoPowerOff] = HttpSetting[Params.AutoPowerOff]( + communicator, SettingId.AUTO_POWER_OFF + ) + + self.photo_mode_v2: HttpSetting[Params.PhotoModeV2] = HttpSetting[Params.PhotoModeV2]( + communicator, SettingId.PHOTO_MODE_V2 + ) + + self.video_digital_lens_v2: HttpSetting[Params.VideoLensV2] = HttpSetting[Params.VideoLensV2]( + communicator, SettingId.VIDEO_DIGITAL_LENSES_V2 + ) + + self.photo_digital_lens_v2: HttpSetting[Params.PhotoLensV2] = HttpSetting[Params.PhotoLensV2]( + communicator, SettingId.PHOTO_DIGITAL_LENSES_V2 + ) + + self.timelapse_digital_lens_v2: HttpSetting[Params.TimelapseLensV2] = HttpSetting[Params.TimelapseLensV2]( + communicator, SettingId.TIMELAPSE_DIGITAL_LENSES_V2 + ) + + self.video_framing: HttpSetting[Params.VideoFraming] = HttpSetting[Params.VideoFraming]( + communicator, SettingId.VIDEO_FRAMING + ) + + self.multi_shot_framing: HttpSetting[Params.MultishotFraming] = HttpSetting[Params.MultishotFraming]( + communicator, SettingId.MULTI_SHOT_FRAMING + ) + + self.frame_rate: HttpSetting[Params.FrameRate] = HttpSetting[Params.FrameRate]( + communicator, SettingId.FRAME_RATE + ) + super().__init__(communicator) diff --git a/demos/python/sdk_wireless_camera_control/open_gopro/api/params.py b/demos/python/sdk_wireless_camera_control/open_gopro/api/params.py index 2fcd2594..b5ecdb38 100644 --- a/demos/python/sdk_wireless_camera_control/open_gopro/api/params.py +++ b/demos/python/sdk_wireless_camera_control/open_gopro/api/params.py @@ -1,9 +1,9 @@ -# params.py/Open GoPro, Version 2.0 (C) Copyright 2021 GoPro, Inc. (http://gopro.com/OpenGoPro). +# params.py/Open GoPro, Version 2_0 (C) Copyright 2021 GoPro, Inc. (http://gopro.com/OpenGoPro). # This copyright was auto-generated on Tue Sep 7 21:35:52 UTC 2021 # pylint: disable=missing-class-docstring, no-member -"""Parameter definitions for GoPro BLE and WiFi commands for Open GoPro version 2.0""" +"""Parameter definitions for GoPro BLE and WiFi commands for Open GoPro version 2_0""" from __future__ import annotations @@ -449,3 +449,152 @@ class VideoDuration(GoProIntEnum): DUR_3_HOURS = 9 DUR_5_SECONDS = 10 DUR_NO_LIMIT = 100 + + +class AutoPowerOff(GoProIntEnum): + NEVER = 0 + MIN_1 = 1 + MIN_5 = 4 + MIN_15 = 6 + MIN_30 = 7 + + +class RegionalFormat(GoProIntEnum): + HZ_60 = 0 + HZ_50 = 1 + + +class QualityControl(GoProIntEnum): + HIGHEST = 0 + STANDARD = 1 + BASIC = 2 + + +class Volume(GoProIntEnum): + LOW = 70 + MEDIUM = 85 + HIGH = 100 + + +class LensModStatus(GoProIntEnum): + INVALID = -1 + DEFAULT = 0 + MAX_LENS = 1 + MAX_LENS_2_0 = 2 + MAX_LENS_2_5 = 3 + MACRO = 4 + ANAMORPHIC = 5 + ND_4 = 6 + ND_8 = 7 + ND_16 = 8 + ND_32 = 9 + NONE = 10 + + +class LensAttachment(GoProIntEnum): + MAX_LENS_2_0 = 2 + MAX_LENS_2_5 = 3 + MACRO = 4 + ND_4 = 6 + ND_8 = 7 + ND_16 = 8 + ND_32 = 9 + STANDARD_LENS = 10 + AUTO_DETECT = 100 + + +class ScreenSaverTimeout(GoProIntEnum): + NEVER = 0 + MIN_1 = 1 + MIN_2 = 2 + MIN_3 = 3 + MIN_5 = 4 + + +class SetupLanguage(GoProIntEnum): + ENGLISH_US = 0 + ENGLISH_UK = 1 + ENGLISH_AUS = 2 + GERMAN = 3 + FRENCH = 4 + ITALIAN = 5 + SPANISH = 6 + SPANISH_NA = 7 + CHINESE = 8 + JAPANESE = 9 + KOREAN = 10 + PORTUGUESE = 11 + RUSSIAN = 12 + ENGLISH_IND = 13 + SWEDISH = 14 + + +class PhotoModeV2(GoProIntEnum): + SUPER = 0 + NIGHT = 1 + BURST = 2 + + +class VideoLensV2(GoProIntEnum): + WIDE = 0 + NARROW = 2 + SUPERVIEW = 3 + LINEAR = 4 + LINEAR_HORIZON_LEVELING = 8 + HYPERVIEW = 9 + LINEAR_HORIZON_LOCK = 10 + MAX_HYPERVIEW = 11 + ULTRA_SUPERVIEW = 12 + ULTRA_WIDE = 13 + ULTRA_HYPERVIEW = 100 + + +class PhotoLensV2(GoProIntEnum): + MP_12_WIDE = 0 + MP_12_LINEAR = 10 + MP_9_WIDE = 15 + MP_23_WIDE = 27 + MP_23_LINEAR = 28 + MP_27_WIDE = 31 + MP_27_LINEAR = 32 + MP_9_LINEAR = 37 + MP_13_LINEAR = 38 + MP_13_WIDE = 39 + MP_13_ULTRA_WIDE = 40 + MP_12_ULTRA_WIDE = 41 + + +class TimelapseLensV2(GoProIntEnum): + MP_27_WIDE = 31 + MP_27_LINEAR = 32 + + +class VideoFraming(GoProIntEnum): + FRAMING_4_3 = 0 + FRAMING_16_9 = 1 + FRAMING_8_7 = 3 + FRAMING_9_16 = 4 + FRAMING_1_1 = 6 + + +class MultishotFraming(GoProIntEnum): + FRAMING_4_3 = 0 + FRAMING_16_9 = 1 + FRAMING_8_7 = 3 + FRAMING_9_16 = 4 + + +class FrameRate(GoProIntEnum): + FRAME_RATE_240_0 = 0 + FRAME_RATE_120_0 = 1 + FRAME_RATE_100_0 = 2 + FRAME_RATE_90_0 = 3 + FRAME_RATE_60_0 = 5 + FRAME_RATE_50_0 = 6 + FRAME_RATE_30_0 = 8 + FRAME_RATE_25_0 = 9 + FRAME_RATE_24_0 = 10 + FRAME_RATE_200_0 = 13 + FRAME_RATE_400_0 = 15 + FRAME_RATE_360_0 = 16 + FRAME_RATE_300_0 = 17 diff --git a/demos/python/sdk_wireless_camera_control/open_gopro/constants.py b/demos/python/sdk_wireless_camera_control/open_gopro/constants.py index 29353eb5..626ff4d1 100644 --- a/demos/python/sdk_wireless_camera_control/open_gopro/constants.py +++ b/demos/python/sdk_wireless_camera_control/open_gopro/constants.py @@ -262,8 +262,48 @@ class SettingId(GoProIntEnum): PHOTO_MODE = 191 MULTI_SHOT_NLV_ASPECT_RATIO = 192 FRAMING = 193 + INTERNAL_194 = 194 + REGIONAL_FORMAT = 195 + INTERNAL_196 = 196 + INTERNAL_197 = 197 + INTERNAL_198 = 198 + INTERNAL_199 = 199 + INTERNAL_200 = 200 + QUALITY_CONTROL = 201 + INTERNAL_202 = 202 + INTERNAL_203 = 203 + INTERNAL_204 = 204 + INTERNAL_205 = 205 + INTERNAL_206 = 206 + INTERNAL_207 = 207 + INTERNAL_208 = 208 + INTERNAL_209 = 209 + INTERNAL_210 = 210 + INTERNAL_211 = 211 + INTERNAL_212 = 212 + INTERNAL_213 = 213 + INTERNAL_214 = 214 + INTERNAL_215 = 215 + CAMERA_VOLUME = 216 + LENS_ATTACHMENT = 217 + INTERNAL_218 = 218 + SETUP_SCREEN_SAVER = 219 + INTERNAL_220 = 220 + INTERNAL_221 = 221 + INTERNAL_222 = 222 + SETUP_LANGUAGE = 223 + INTERNAL_224 = 224 + AUTO_POWER_OFF = 225 + INTERNAL_226 = 226 + PHOTO_MODE_V2 = 227 + INTERNAL_228 = 228 + VIDEO_DIGITAL_LENSES_V2 = 229 + PHOTO_DIGITAL_LENSES_V2 = 230 + TIMELAPSE_DIGITAL_LENSES_V2 = 231 + VIDEO_FRAMING = 232 + MULTI_SHOT_FRAMING = 233 + FRAME_RATE = 234 PROTOBUF_SETTING = 0xF3 - INVALID_FOR_TESTING = 0xFF class QueryCmdId(GoProIntEnum): @@ -284,7 +324,6 @@ class QueryCmdId(GoProIntEnum): STATUS_VAL_PUSH = 0x93 SETTING_CAPABILITY_PUSH = 0xA2 PROTOBUF_QUERY = 0xF5 - INVALID_FOR_TESTING = 0xFF class StatusId(GoProIntEnum): @@ -392,6 +431,8 @@ class StatusId(GoProIntEnum): USB_CONNECTED = 115 CONTROL_OVER_USB = 116 TOTAL_SD_SPACE_KB = 117 + PHOTO_INTERVAL_CAPTURE_COUNT = 118 + CAMERA_LENS_MOD = 119 class WebcamStatus(GoProIntEnum): diff --git a/demos/python/sdk_wireless_camera_control/open_gopro/demos/custom_preset_udpate_demo.py b/demos/python/sdk_wireless_camera_control/open_gopro/demos/custom_preset_udpate_demo.py deleted file mode 100644 index 17de6b68..00000000 --- a/demos/python/sdk_wireless_camera_control/open_gopro/demos/custom_preset_udpate_demo.py +++ /dev/null @@ -1,64 +0,0 @@ -# custom_preset_udpate_demo.py/Open GoPro, Version 2.0 (C) Copyright 2021 GoPro, Inc. (http://gopro.com/OpenGoPro). -# This copyright was auto-generated on Thu Mar 28 20:25:41 UTC 2024 - -"""Simple demo to modify a currently accessible custom preset's title and icon.""" - -import asyncio -from pathlib import Path - -from rich.console import Console - -from open_gopro import WiredGoPro, proto -from open_gopro.logger import setup_logging - -console = Console() - - -async def main() -> None: - logger = setup_logging(__name__, Path("custom_preset.log")) - gopro: WiredGoPro | None = None - - try: - async with WiredGoPro() as gopro: - presets = (await gopro.http_command.get_preset_status()).data - custom_preset_id: int | None = None - for group in presets["presetGroupArray"]: - for preset in group["presetArray"]: - if preset["userDefined"]: - custom_preset_id = preset["id"] - if not custom_preset_id: - raise RuntimeError("Could not find a custom preset.") - # Ensure we can load it - assert (await gopro.http_command.load_preset(preset=custom_preset_id)).ok - # Now try to update it - assert ( - await gopro.http_command.update_custom_preset( - icon_id=proto.EnumPresetIcon.PRESET_ICON_SNOW, - title_id=proto.EnumPresetTitle.PRESET_TITLE_SNOW, - ) - ).ok - input("press enter to continue") - assert ( - await gopro.http_command.update_custom_preset( - icon_id=proto.EnumPresetIcon.PRESET_ICON_MOTOR, - title_id=proto.EnumPresetTitle.PRESET_TITLE_MOTOR, - ) - ).ok - input("press enter to continue") - assert ( - await gopro.http_command.update_custom_preset( - custom_name="Custom Name", - icon_id=proto.EnumPresetIcon.PRESET_ICON_BIKE, - title_id=proto.EnumPresetTitle.PRESET_TITLE_USER_DEFINED_CUSTOM_NAME, - ) - ).ok - - except Exception as e: # pylint: disable = broad-except - logger.error(repr(e)) - - if gopro: - await gopro.close() - - -if __name__ == "__main__": - asyncio.run(main()) diff --git a/demos/python/sdk_wireless_camera_control/open_gopro/demos/video.py b/demos/python/sdk_wireless_camera_control/open_gopro/demos/video.py index 04372092..2c7a1744 100644 --- a/demos/python/sdk_wireless_camera_control/open_gopro/demos/video.py +++ b/demos/python/sdk_wireless_camera_control/open_gopro/demos/video.py @@ -33,11 +33,9 @@ async def main(args: argparse.Namespace) -> None: media_set_before = set((await gopro.http_command.get_media_list()).data.files) # Take a video console.print("Capturing a video...") - # assert (await gopro.http_command.set_shutter(shutter=Params.Toggle.ENABLE)).ok - # await asyncio.sleep(args.record_time) - # assert (await gopro.http_command.set_shutter(shutter=Params.Toggle.DISABLE)).ok - assert await gopro.http_setting.video_duration.set(Params.VideoDuration.DUR_15_SECONDS) assert (await gopro.http_command.set_shutter(shutter=Params.Toggle.ENABLE)).ok + await asyncio.sleep(args.record_time) + assert (await gopro.http_command.set_shutter(shutter=Params.Toggle.DISABLE)).ok # Get the media list after media_set_after = set((await gopro.http_command.get_media_list()).data.files)