Camera - Blueye SDK

Skip to content

# Module blueye.sdk.camera

None

None

View Source

    from __future__ import annotations

    import re

    import warnings

    from collections import namedtuple

    from enum import Enum

    from typing import TYPE_CHECKING, NamedTuple

    import numpy as np

    import requests

    # Necessary to avoid cyclic imports

    if TYPE_CHECKING:

        from .drone import Drone

    class Tilt:

        @staticmethod

        def _tilt_angle_from_debug_flags(flags: int) -> float:

            """Helper function for decoding tilt angle from debug flags

            The tilt angle is encoded as an int8, with 0 at 0 degrees, and each increment representing

            0.5 degrees in either direction. A positive angle is upwards, and negative is downwards.

            """

            TILT_ANGLE_MASK = 0x0000FF0000000000

            TILT_ANGLE_OFFSET = 40

            tilt_angle_array = np.array(

                np.right_shift(np.bitwise_and(flags, TILT_ANGLE_MASK), TILT_ANGLE_OFFSET),

                dtype=[("tilt_angle", np.int8)],

            ).astype([("tilt_angle", float)])

            return tilt_angle_array["tilt_angle"] / 2

        @staticmethod

        def _tilt_stabilization_status_from_debug_flags(flags: int) -> bool:

            """Helper function for decoding tilt stabilization status from debug flags"""

            TILT_STABILIZATION_MASK = 0x100

            return bool(flags & TILT_STABILIZATION_MASK)

        def __init__(self, parent_drone: Drone):

            self._parent_drone = parent_drone

        def _verify_tilt_in_features(self):

            """Checks that the connected drone has the tilt feature

            Raises a RuntimeError if it does not.

            """

            if "tilt" not in self._parent_drone.features:

                raise RuntimeError("The connected drone does not support tilting the camera.")

        def set_speed(self, speed: float):

            """Set the speed and direction of the camera tilt

            *Arguments*:

            * speed (float): Speed and direction of the tilt. 1 is max speed up, -1 is max speed down.

            Requires a drone with the tilt feature, and software version 1.5 or newer.

            A RuntimeError is raised if either of those requirements are not met.

            """

            self._parent_drone._verify_required_blunux_version("1.5")

            self._verify_tilt_in_features()

            # The tilt command is grouped together with the thruster commands, so to avoid messing with

            # the thruster setpoint while tilting we need to get the current setpoint and send it with

            # the tilt command.

            with self._parent_drone.motion.thruster_lock:

                thruster_setpoints = self._parent_drone.motion.current_thruster_setpoints.values()

                self._parent_drone._tcp_client.motion_input_tilt(*thruster_setpoints, 0, 0, speed)

        @property

        def angle(self) -> float:

            """Return the current angle of the camera tilt

            Requires a drone with the tilt feature, and software version 1.5 or newer.

            A RuntimeError is raised if either of those requirements are not met.

            """

            self._parent_drone._verify_required_blunux_version("1.5")

            self._verify_tilt_in_features()

            debug_flags = self._parent_drone._state_watcher.general_state["debug_flags"]

            return self._tilt_angle_from_debug_flags(debug_flags)

        @property

        def stabilization_enabled(self) -> bool:

            """Get the state of active camera stabilization

            Use the `toggle_stabilization` method to turn stabilization on or off

            *Returns*:

            * Current state of active camera stabilization (bool)

            """

            self._parent_drone._verify_required_blunux_version("1.6.42")

            self._verify_tilt_in_features()

            debug_flags = self._parent_drone._state_watcher.general_state["debug_flags"]

            return self._tilt_stabilization_status_from_debug_flags(debug_flags)

        def toggle_stabilization(self):

            """Toggle active camera stabilization on or off

            Requires a drone with the tilt feature, and Blunux version 1.6.42 or newer.

            A RuntimeError is raised if either of those requirements are not met.

            """

            self._parent_drone._verify_required_blunux_version("1.6.42")

            self._verify_tilt_in_features()

            self._parent_drone._tcp_client.toggle_tilt_stabilization()

    class LogoOverlay(Enum):

        DISABLED = 0

        BLUEYE = 1

        CUSTOM = 2

    class DepthUnitOverlay(Enum):

        METERS = 0

        FEET = 1

    class TemperatureUnitOverlay(Enum):

        CELSIUS = 0

        FAHRENHEIT = 1

    class FontSizeOverlay(Enum):

        PX15 = 15

        PX20 = 20

        PX25 = 25

        PX30 = 30

        PX35 = 35

        PX40 = 40

    class Overlay:

        """Control the overlay on videos and pictures"""

        def __init__(self, parent_drone: Drone):

            self._parent_drone = parent_drone

        def _get_named_overlay_parameters(self) -> NamedTuple:

            """Get overlay parameters from drone and convert them to a named tuple"""

            NamedParameters = namedtuple(

                "Parameters",

                [

                    "returned_parameter",

                    "temperature_enabled",

                    "depth_enabled",

                    "heading_enabled",

                    "tilt_enabled",

                    "date_enabled",

                    "logo_index",

                    "depth_unit",

                    "temperature_unit",

                    "tz_offset",

                    "margin_width",

                    "margin_height",

                    "font_size",

                    "title",

                    "subtitle",

                    "date_format",

                ],

            )

            parameters = self._parent_drone._tcp_client.get_overlay_parameters()

            return NamedParameters(*parameters)

        @property

        def temperature_enabled(self) -> bool:

            """Get or set the state of the temperature overlay

            Requires Blunux version 1.7.60 or newer.

            """

            self._parent_drone._verify_required_blunux_version("1.7.60")

            return bool(self._get_named_overlay_parameters().temperature_enabled)

        @temperature_enabled.setter

        def temperature_enabled(self, enable_temperature: bool):

            self._parent_drone._verify_required_blunux_version("1.7.60")

            self._parent_drone._tcp_client.set_overlay_temperature_enabled(

                1 if enable_temperature else 0

            )

        @property

        def depth_enabled(self) -> bool:

            """Get or set the state of the depth overlay

            Requires Blunux version 1.7.60 or newer.

            """

            self._parent_drone._verify_required_blunux_version("1.7.60")

            return bool(self._get_named_overlay_parameters().depth_enabled)

        @depth_enabled.setter

        def depth_enabled(self, enable_depth: bool):

            self._parent_drone._verify_required_blunux_version("1.7.60")

            self._parent_drone._tcp_client.set_overlay_depth_enabled(1 if enable_depth else 0)

        @property

        def heading_enabled(self) -> bool:

            """Get or set the state of the heading overlay

            Requires Blunux version 1.7.60 or newer.

            """

            self._parent_drone._verify_required_blunux_version("1.7.60")

            return bool(self._get_named_overlay_parameters().heading_enabled)

        @heading_enabled.setter

        def heading_enabled(self, enable_heading: bool):

            self._parent_drone._verify_required_blunux_version("1.7.60")

            self._parent_drone._tcp_client.set_overlay_heading_enabled(1 if enable_heading else 0)

        @property

        def tilt_enabled(self) -> bool:

            """Get or set the state of the tilt overlay

            Requires Blunux version 1.7.60 or newer.

            """

            self._parent_drone._verify_required_blunux_version("1.7.60")

            return bool(self._get_named_overlay_parameters().tilt_enabled)

        @tilt_enabled.setter

        def tilt_enabled(self, enable_tilt: bool):

            self._parent_drone._verify_required_blunux_version("1.7.60")

            self._parent_drone._tcp_client.set_overlay_tilt_enabled(1 if enable_tilt else 0)

        @property

        def date_enabled(self) -> bool:

            """Get or set the state of the date overlay

            Requires Blunux version 1.7.60 or newer.

            """

            self._parent_drone._verify_required_blunux_version("1.7.60")

            return bool(self._get_named_overlay_parameters().date_enabled)

        @date_enabled.setter

        def date_enabled(self, enable_date: bool):

            self._parent_drone._verify_required_blunux_version("1.7.60")

            self._parent_drone._tcp_client.set_overlay_date_enabled(1 if enable_date else 0)

        @property

        def logo(self) -> LogoOverlay:

            """Get or set logo overlay selection

            Needs to be set to an instance of the `LogoOverlay` class, if not a RuntimeWarning is

            raised.

            Requires Blunux version 1.8.72 or newer.

            """

            self._parent_drone._verify_required_blunux_version("1.8.72")

            return LogoOverlay(self._get_named_overlay_parameters().logo_index)

        @logo.setter

        def logo(self, logo_index: LogoOverlay):

            self._parent_drone._verify_required_blunux_version("1.8.72")

            if not isinstance(logo_index, LogoOverlay):

                warnings.warn("Invalid logo index, ignoring", RuntimeWarning)

            elif logo_index.value not in range(3):

                warnings.warn("Logo index out of range, ignoring", RuntimeWarning)

            else:

                self._parent_drone._tcp_client.set_overlay_logo_index(logo_index.value)

        @property

        def depth_unit(self) -> DepthUnitOverlay:

            """Get or set the depth unit for the overlay

            Needs to be set to an instance of the `DepthUnitOverlay` class, if not a RuntimeWarning is

            raised.

            Requires Blunux version 1.7.60 or newer.

            """

            self._parent_drone._verify_required_blunux_version("1.7.60")

            return DepthUnitOverlay(self._get_named_overlay_parameters().depth_unit)

        @depth_unit.setter

        def depth_unit(self, unit_index: DepthUnitOverlay):

            self._parent_drone._verify_required_blunux_version("1.7.60")

            if not isinstance(unit_index, DepthUnitOverlay):

                warnings.warn("Invalid depth unit index, ignoring", RuntimeWarning)

            elif unit_index.value not in range(2):

                warnings.warn("Depth unit index out of range, ignoring", RuntimeWarning)

            else:

                self._parent_drone._tcp_client.set_overlay_depth_unit(unit_index.value)

        @property

        def temperature_unit(self) -> TemperatureUnitOverlay:

            """Get or set the temperature unit for the overlay

            Needs to be set to an instance of the `TemperatureUnitOverlay` class, if not a

            RuntimeWarning is raised.

            Requires Blunux version 1.7.60 or newer.

            """

            self._parent_drone._verify_required_blunux_version("1.7.60")

            return TemperatureUnitOverlay(self._get_named_overlay_parameters().temperature_unit)

        @temperature_unit.setter

        def temperature_unit(self, unit_index: TemperatureUnitOverlay):

            self._parent_drone._verify_required_blunux_version("1.7.60")

            if not isinstance(unit_index, TemperatureUnitOverlay):

                warnings.warn("Invalid temperature unit index, ignoring", RuntimeWarning)

            elif unit_index.value not in range(2):

                warnings.warn("Temperature unit index out of range, ignoring", RuntimeWarning)

            else:

                self._parent_drone._tcp_client.set_overlay_temperature_unit(unit_index.value)

        @property

        def timezone_offset(self) -> int:

            """Get or set the timezone offset for the overlay

            Set to the number of minutes (either positive or negative) the timestamp should be offset.

            Requires Blunux version 1.7.60 or newer.

            """

            self._parent_drone._verify_required_blunux_version("1.7.60")

            return self._get_named_overlay_parameters().tz_offset

        @timezone_offset.setter

        def timezone_offset(self, offset: int):

            self._parent_drone._verify_required_blunux_version("1.7.60")

            self._parent_drone._tcp_client.set_overlay_tz_offset(offset)

        @property

        def margin_width(self) -> int:

            """Get or set the margin width for the overlay

            The amount of pixels to use as margin on the right and left side of the overlay. Needs to

            be a positive integer.

            Requires Blunux version 1.7.60 or newer.

            """

            self._parent_drone._verify_required_blunux_version("1.7.60")

            return self._get_named_overlay_parameters().margin_width

        @margin_width.setter

        def margin_width(self, width: int):

            self._parent_drone._verify_required_blunux_version("1.7.60")

            if width < 0:

                warnings.warn("Invalid margin width, ignoring", RuntimeWarning)

            else:

                self._parent_drone._tcp_client.set_overlay_margin_width(width)

        @property

        def margin_height(self) -> int:

            """Get or set the margin height for the overlay

            The amount of pixels to use as margin on the top and bottom side of the overlay. Needs to be

            a positive integer.

            Requires Blunux version 1.7.60 or newer.

            """

            self._parent_drone._verify_required_blunux_version("1.7.60")

            return self._get_named_overlay_parameters().margin_height

        @margin_height.setter

        def margin_height(self, height: int):

            self._parent_drone._verify_required_blunux_version("1.7.60")

            if height < 0:

                warnings.warn("Invalid margin height, ignoring", RuntimeWarning)

            else:

                self._parent_drone._tcp_client.set_overlay_margin_height(height)

        @property

        def font_size(self) -> FontSizeOverlay:

            """Get or set the font size for the overlay

            Needs to be an instance of the `FontSizeOverlay` class, if not a RuntimeWarning is raised.

            Requires Blunux version 1.7.60 or newer.

            """

            self._parent_drone._verify_required_blunux_version("1.7.60")

            return FontSizeOverlay(self._get_named_overlay_parameters().font_size)

        @font_size.setter

        def font_size(self, size: FontSizeOverlay):

            self._parent_drone._verify_required_blunux_version("1.7.60")

            if not isinstance(size, FontSizeOverlay):

                warnings.warn("Invalid font size, ignoring", RuntimeWarning)

            elif size.value not in range(15, 41):

                warnings.warn("Font size out of range, ignoring", RuntimeWarning)

            else:

                self._parent_drone._tcp_client.set_overlay_font_size(size.value)

        @property

        def title(self) -> str:

            """Get or set the title for the overlay

            The title needs to be a string of only ASCII characters with a maximum length of 63

            characters. If a longer title is passed it will be truncated, and a RuntimeWarning is

            raised.

            Set to an empty string to disable title.

            Requires Blunux version 1.7.60 or newer.

            """

            self._parent_drone._verify_required_blunux_version("1.7.60")

            return self._get_named_overlay_parameters().title.decode("utf-8").rstrip("\x00")

        @title.setter

        def title(self, input_title: str):

            self._parent_drone._verify_required_blunux_version("1.7.60")

            new_title = input_title

            if len(input_title) > 63:

                warnings.warn("Too long title, truncating to 63 characters", RuntimeWarning)

                new_title = new_title[:63]

            try:

                encoded_title = bytes(new_title, "ascii")

            except UnicodeEncodeError:

                warnings.warn("Title can only contain ASCII characters, ignoring", RuntimeWarning)

                return

            self._parent_drone._tcp_client.set_overlay_title(encoded_title + b"\x00")

        @property

        def subtitle(self) -> str:

            """Get or set the subtitle for the overlay

            The subtitle needs to be a string of only ASCII characters with a maximum length of 63

            characters. If a longer subtitle is passed it will be truncated, and a RuntimeWarning is

            raised.

            Set to an empty string to disable the subtitle.

            Requires Blunux version 1.7.60 or newer.

            """

            self._parent_drone._verify_required_blunux_version("1.7.60")

            return self._get_named_overlay_parameters().subtitle.decode("utf-8").rstrip("\x00")

        @subtitle.setter

        def subtitle(self, input_subtitle: str):

            self._parent_drone._verify_required_blunux_version("1.7.60")

            new_subtitle = input_subtitle

            if len(input_subtitle) > 63:

                warnings.warn("Too long subtitle, truncating to 63 characters", RuntimeWarning)

                new_subtitle = new_subtitle[:63]

            try:

                encoded_subtitle = bytes(new_subtitle, "ascii")

            except UnicodeEncodeError:

                warnings.warn("Subtitle can only contain ASCII characters, ignoring", RuntimeWarning)

                return

            self._parent_drone._tcp_client.set_overlay_subtitle(encoded_subtitle + b"\x00")

        @property

        def date_format(self) -> str:

            """Get or set the format string for the time displayed in the overlay

            Must be a string containing only ASCII characters, with a max length of 63 characters.

            The format codes are defined by the C89 standard, see

            https://docs.python.org/3/library/datetime.html#strftime-and-strptime-format-codes

            for an overview of the available codes.

            """

            self._parent_drone._verify_required_blunux_version("1.7.60")

            return self._get_named_overlay_parameters().date_format.decode("utf-8").rstrip("\x00")

        @date_format.setter

        def date_format(self, input_format_str: str):

            self._parent_drone._verify_required_blunux_version("1.7.60")

            format_str = input_format_str

            if len(format_str) > 63:

                warnings.warn(

                    "Too long date format string, truncating to 63 characters", RuntimeWarning

                )

                format_str = format_str[:63]

            try:

                encoded_format_str = bytes(format_str, "ascii")

            except UnicodeEncodeError:

                warnings.warn(

                    "Date format string can only contain ASCII characters, ignoring", RuntimeWarning

                )

                return

            self._parent_drone._tcp_client.set_overlay_date_format(encoded_format_str + b"\x00")

        def upload_logo(self, path_to_logo: str):

            """Upload user selectable logo for watermarking videos and pictures

            Set the logo-property to `LogoOverlay.CUSTOM` to enable this logo.

            Allowed filetype: JPG or PNG.

            Max resolution: 2000 px.

            Max file size: 5 MB.

            Requires Blunux version 1.8.72 or newer.

            *Exceptions*:

            * `requests.exceptions.HTTPError` : Status code 400 for invalid files

            * `requests.exceptions.ConnectTimeout` : If unable to create a connection within 1s

            """

            self._parent_drone._verify_required_blunux_version("1.8.72")

            with open(path_to_logo, "rb") as f:

                url = f"http://{self._parent_drone._ip}/asset/logo"

                files = {"image": f}

                response = requests.post(url, files=files, timeout=1)

            response.raise_for_status()

        def download_logo(self, output_directory="."):

            """Download the original user uploaded logo (PNG or JPG)

            Select the download directory with the output_directory parameter.

            *Exceptions*:

            * `requests.exceptions.HTTPError` : If no custom logo is uploaded.

            * `requests.exceptions.ConnectTimeout` : If unable to create a connection within 1s

            """

            self._parent_drone._verify_required_blunux_version("1.8.72")

            response = requests.get(f"http://{self._parent_drone._ip}/asset/logo", timeout=1)

            response.raise_for_status()

            filename = re.findall('filename="(.+)"', response.headers["Content-Disposition"])[0]

            with open(f"{output_directory}/{filename}", "wb") as f:

                f.write(response.content)

        def delete_logo(self):

            """Delete the user uploaded logo from the drone

            *Exceptions*:

            * `requests.exceptions.HTTPError` : If an error occurs during deletion

            * `requests.exceptions.ConnectTimeout` : If unable to create a connection within 1s

            """

            self._parent_drone._verify_required_blunux_version("1.8.72")

            response = requests.delete(f"http://{self._parent_drone._ip}/asset/logo", timeout=1)

            response.raise_for_status()

    class Camera:

        def __init__(self, parent_drone: Drone):

            self._state_watcher = parent_drone._state_watcher

            self._parent_drone = parent_drone

            self.tilt = Tilt(parent_drone)

            self.overlay = Overlay(parent_drone)

        @property

        def is_recording(self) -> bool:

            """Start or stop a camera recording

            *Arguments*:

            * is_recording (bool): Set to True to start a recording, set to False to stop the current recording

            *Returns*:

            * is_recording (bool): True if the camera is currently recording, False if not

            """

            state = self._state_watcher.general_state

            if state["camera_record_time"] != -1:

                return True

            else:

                return False

        @is_recording.setter

        def is_recording(self, start_recording: bool):

            if start_recording:

                self._parent_drone._tcp_client.start_recording()

            else:

                self._parent_drone._tcp_client.stop_recording()

        @property

        def bitrate(self) -> int:

            """Set or get the camera bitrate

            *Arguments*:

            * bitrate (int): Set the camera bitrate in bits, Valid values are in range <1 000 000, 16 000 000>

            *Returns*:

            * bitrate (int): Get the camera bitrate

            """

            camera_parameters = self._parent_drone._tcp_client.get_camera_parameters()

            bitrate = camera_parameters[1]

            return bitrate

        @bitrate.setter

        def bitrate(self, bitrate: int):

            self._parent_drone._tcp_client.set_camera_bitrate(bitrate)

        @property

        def exposure(self) -> int:

            """Set or get the camera exposure

            *Arguments*:

            * exposure (int): Set the camera exposure_value: 1 = 1/1000th of a second, 5 = 1/200th of a second. Valid values are in the range <1, 5000>

            *Returns*:

            * exposure (int): Get the camera exposure

            """

            camera_parameters = self._parent_drone._tcp_client.get_camera_parameters()

            exposure = camera_parameters[2]

            return exposure

        @exposure.setter

        def exposure(self, exposure: int):

            self._parent_drone._tcp_client.set_camera_exposure(exposure)

        @property

        def whitebalance(self) -> int:

            """Set or get the camera white balance

            *Arguments*:

            * whitebalance (int): Set the camera white balance. Valid values are in the range <2800, 9300>

            *Returns*:

            * whitebalance (int): Get the camera white balance

            """

            camera_parameters = self._parent_drone._tcp_client.get_camera_parameters()

            whitebalance = camera_parameters[3]

            return whitebalance

        @whitebalance.setter

        def whitebalance(self, whitebalance: int):

            self._parent_drone._tcp_client.set_camera_whitebalance(whitebalance)

        @property

        def hue(self) -> int:

            """Set or get the camera hue

            *Arguments*:

            * hue (int): Set the camera hue. Valid values are in the range <-40, 40>

            *Returns*:

            * hue (int): Get the camera hue

            """

            camera_parameters = self._parent_drone._tcp_client.get_camera_parameters()

            hue = camera_parameters[4]

            return hue

        @hue.setter

        def hue(self, hue: int):

            self._parent_drone._tcp_client.set_camera_hue(hue)

        @property

        def resolution(self) -> int:

            """Set or get the camera resolution

            *Arguments*:

            * resolution (int): Set the camera in vertical pixels. Valid values are 720 or 1080

            *Returns*:

            * resolution (int): Get the camera resolution

            """

            camera_parameters = self._parent_drone._tcp_client.get_camera_parameters()

            resolution = camera_parameters[5]

            return resolution

        @resolution.setter

        def resolution(self, resolution: int):

            self._parent_drone._tcp_client.set_camera_resolution(resolution)

        @property

        def framerate(self) -> int:

            """Set or get the camera frame rate

            *Arguments*:

            * framerate (int): Set the camera frame rate in frames per second. Valid values are 25 or 30

            *Returns*:

            * framerate (int): Get the camera frame rate

            """

            camera_parameters = self._parent_drone._tcp_client.get_camera_parameters()

            framerate = camera_parameters[6]

            return framerate

        @framerate.setter

        def framerate(self, framerate: int):

            self._parent_drone._tcp_client.set_camera_framerate(framerate)

        @property

        def record_time(self) -> int:

            """Set or get the duration of the current camera recording

            *Returns*:

            * record_time (int): The length in seconds of the current recording, -1 if the camera is not currently recording

            """

            return self._state_watcher.general_state["camera_record_time"]

        def take_picture(self):

            """Takes a still picture and stores it locally on the drone

            These pictures can be downloaded with the Blueye App, or by any WebDAV compatible client.

            This feature was added with drone version 1.4.7, so if you try to use it with an older

            version this method will raise a RunTimeError.

            """

            self._parent_drone._verify_required_blunux_version("1.4.7")

            self._parent_drone._tcp_client.take_still_picture()

## Variables

    TYPE_CHECKING

## Classes

### Camera

    class Camera(
        parent_drone: 'Drone'
    )

View Source

    class Camera:

        def __init__(self, parent_drone: Drone):

            self._state_watcher = parent_drone._state_watcher

            self._parent_drone = parent_drone

            self.tilt = Tilt(parent_drone)

            self.overlay = Overlay(parent_drone)

        @property

        def is_recording(self) -> bool:

            """Start or stop a camera recording

            *Arguments*:

            * is_recording (bool): Set to True to start a recording, set to False to stop the current recording

            *Returns*:

            * is_recording (bool): True if the camera is currently recording, False if not

            """

            state = self._state_watcher.general_state

            if state["camera_record_time"] != -1:

                return True

            else:

                return False

        @is_recording.setter

        def is_recording(self, start_recording: bool):

            if start_recording:

                self._parent_drone._tcp_client.start_recording()

            else:

                self._parent_drone._tcp_client.stop_recording()

        @property

        def bitrate(self) -> int:

            """Set or get the camera bitrate

            *Arguments*:

            * bitrate (int): Set the camera bitrate in bits, Valid values are in range <1 000 000, 16 000 000>

            *Returns*:

            * bitrate (int): Get the camera bitrate

            """

            camera_parameters = self._parent_drone._tcp_client.get_camera_parameters()

            bitrate = camera_parameters[1]

            return bitrate

        @bitrate.setter

        def bitrate(self, bitrate: int):

            self._parent_drone._tcp_client.set_camera_bitrate(bitrate)

        @property

        def exposure(self) -> int:

            """Set or get the camera exposure

            *Arguments*:

            * exposure (int): Set the camera exposure_value: 1 = 1/1000th of a second, 5 = 1/200th of a second. Valid values are in the range <1, 5000>

            *Returns*:

            * exposure (int): Get the camera exposure

            """

            camera_parameters = self._parent_drone._tcp_client.get_camera_parameters()

            exposure = camera_parameters[2]

            return exposure

        @exposure.setter

        def exposure(self, exposure: int):

            self._parent_drone._tcp_client.set_camera_exposure(exposure)

        @property

        def whitebalance(self) -> int:

            """Set or get the camera white balance

            *Arguments*:

            * whitebalance (int): Set the camera white balance. Valid values are in the range <2800, 9300>

            *Returns*:

            * whitebalance (int): Get the camera white balance

            """

            camera_parameters = self._parent_drone._tcp_client.get_camera_parameters()

            whitebalance = camera_parameters[3]

            return whitebalance

        @whitebalance.setter

        def whitebalance(self, whitebalance: int):

            self._parent_drone._tcp_client.set_camera_whitebalance(whitebalance)

        @property

        def hue(self) -> int:

            """Set or get the camera hue

            *Arguments*:

            * hue (int): Set the camera hue. Valid values are in the range <-40, 40>

            *Returns*:

            * hue (int): Get the camera hue

            """

            camera_parameters = self._parent_drone._tcp_client.get_camera_parameters()

            hue = camera_parameters[4]

            return hue

        @hue.setter

        def hue(self, hue: int):

            self._parent_drone._tcp_client.set_camera_hue(hue)

        @property

        def resolution(self) -> int:

            """Set or get the camera resolution

            *Arguments*:

            * resolution (int): Set the camera in vertical pixels. Valid values are 720 or 1080

            *Returns*:

            * resolution (int): Get the camera resolution

            """

            camera_parameters = self._parent_drone._tcp_client.get_camera_parameters()

            resolution = camera_parameters[5]

            return resolution

        @resolution.setter

        def resolution(self, resolution: int):

            self._parent_drone._tcp_client.set_camera_resolution(resolution)

        @property

        def framerate(self) -> int:

            """Set or get the camera frame rate

            *Arguments*:

            * framerate (int): Set the camera frame rate in frames per second. Valid values are 25 or 30

            *Returns*:

            * framerate (int): Get the camera frame rate

            """

            camera_parameters = self._parent_drone._tcp_client.get_camera_parameters()

            framerate = camera_parameters[6]

            return framerate

        @framerate.setter

        def framerate(self, framerate: int):

            self._parent_drone._tcp_client.set_camera_framerate(framerate)

        @property

        def record_time(self) -> int:

            """Set or get the duration of the current camera recording

            *Returns*:

            * record_time (int): The length in seconds of the current recording, -1 if the camera is not currently recording

            """

            return self._state_watcher.general_state["camera_record_time"]

        def take_picture(self):

            """Takes a still picture and stores it locally on the drone

            These pictures can be downloaded with the Blueye App, or by any WebDAV compatible client.

            This feature was added with drone version 1.4.7, so if you try to use it with an older

            version this method will raise a RunTimeError.

            """

            self._parent_drone._verify_required_blunux_version("1.4.7")

            self._parent_drone._tcp_client.take_still_picture()

#### Instance variables

    bitrate

Set or get the camera bitrate

Arguments:

- bitrate (int): Set the camera bitrate in bits, Valid values are in range <1 000 000, 16 000 000>

Returns:

- bitrate (int): Get the camera bitrate

    exposure

Set or get the camera exposure

Arguments:

- exposure (int): Set the camera exposure_value: 1 = 1/1000th of a second, 5 = 1/200th of a second. Valid values are in the range <1, 5000>

Returns:

- exposure (int): Get the camera exposure

    framerate

Set or get the camera frame rate

Arguments:

- framerate (int): Set the camera frame rate in frames per second. Valid values are 25 or 30

Returns:

- framerate (int): Get the camera frame rate

    hue

Set or get the camera hue

Arguments:

- hue (int): Set the camera hue. Valid values are in the range <-40, 40>

Returns:

- hue (int): Get the camera hue

    is_recording

Start or stop a camera recording

Arguments:

- is_recording (bool): Set to True to start a recording, set to False to stop the current recording

Returns:

- is_recording (bool): True if the camera is currently recording, False if not

    record_time

Set or get the duration of the current camera recording

Returns:

- record_time (int): The length in seconds of the current recording, -1 if the camera is not currently recording

    resolution

Set or get the camera resolution

Arguments:

- resolution (int): Set the camera in vertical pixels. Valid values are 720 or 1080

Returns:

- resolution (int): Get the camera resolution

    whitebalance

Set or get the camera white balance

Arguments:

- whitebalance (int): Set the camera white balance. Valid values are in the range <2800, 9300>

Returns:

- whitebalance (int): Get the camera white balance

#### Methods

#### take_picture

    def take_picture(
        self
    )

Takes a still picture and stores it locally on the drone

These pictures can be downloaded with the Blueye App, or by any WebDAV compatible client. This feature was added with drone version 1.4.7, so if you try to use it with an older version this method will raise a RunTimeError.

View Source

        def take_picture(self):

            """Takes a still picture and stores it locally on the drone

            These pictures can be downloaded with the Blueye App, or by any WebDAV compatible client.

            This feature was added with drone version 1.4.7, so if you try to use it with an older

            version this method will raise a RunTimeError.

            """

            self._parent_drone._verify_required_blunux_version("1.4.7")

            self._parent_drone._tcp_client.take_still_picture()

### DepthUnitOverlay

    class DepthUnitOverlay(
        /,
        *args,
        **kwargs
    )

View Source

    class DepthUnitOverlay(Enum):

        METERS = 0

        FEET = 1

#### Ancestors (in MRO)

- enum.Enum

#### Class variables

    FEET

    METERS

    name

    value

### FontSizeOverlay

    class FontSizeOverlay(
        /,
        *args,
        **kwargs
    )

View Source

    class FontSizeOverlay(Enum):

        PX15 = 15

        PX20 = 20

        PX25 = 25

        PX30 = 30

        PX35 = 35

        PX40 = 40

#### Ancestors (in MRO)

- enum.Enum

#### Class variables

    PX15

    PX20

    PX25

    PX30

    PX35

    PX40

    name

    value

### LogoOverlay

    class LogoOverlay(
        /,
        *args,
        **kwargs
    )

View Source

    class LogoOverlay(Enum):

        DISABLED = 0

        BLUEYE = 1

        CUSTOM = 2

#### Ancestors (in MRO)

- enum.Enum

#### Class variables

    BLUEYE

    CUSTOM

    DISABLED

    name

    value

### Overlay

    class Overlay(
        parent_drone: 'Drone'
    )

View Source

    class Overlay:

        """Control the overlay on videos and pictures"""

        def __init__(self, parent_drone: Drone):

            self._parent_drone = parent_drone

        def _get_named_overlay_parameters(self) -> NamedTuple:

            """Get overlay parameters from drone and convert them to a named tuple"""

            NamedParameters = namedtuple(

                "Parameters",

                [

                    "returned_parameter",

                    "temperature_enabled",

                    "depth_enabled",

                    "heading_enabled",

                    "tilt_enabled",

                    "date_enabled",

                    "logo_index",

                    "depth_unit",

                    "temperature_unit",

                    "tz_offset",

                    "margin_width",

                    "margin_height",

                    "font_size",

                    "title",

                    "subtitle",

                    "date_format",

                ],

            )

            parameters = self._parent_drone._tcp_client.get_overlay_parameters()

            return NamedParameters(*parameters)

        @property

        def temperature_enabled(self) -> bool:

            """Get or set the state of the temperature overlay

            Requires Blunux version 1.7.60 or newer.

            """

            self._parent_drone._verify_required_blunux_version("1.7.60")

            return bool(self._get_named_overlay_parameters().temperature_enabled)

        @temperature_enabled.setter

        def temperature_enabled(self, enable_temperature: bool):

            self._parent_drone._verify_required_blunux_version("1.7.60")

            self._parent_drone._tcp_client.set_overlay_temperature_enabled(

                1 if enable_temperature else 0

            )

        @property

        def depth_enabled(self) -> bool:

            """Get or set the state of the depth overlay

            Requires Blunux version 1.7.60 or newer.

            """

            self._parent_drone._verify_required_blunux_version("1.7.60")

            return bool(self._get_named_overlay_parameters().depth_enabled)

        @depth_enabled.setter

        def depth_enabled(self, enable_depth: bool):

            self._parent_drone._verify_required_blunux_version("1.7.60")

            self._parent_drone._tcp_client.set_overlay_depth_enabled(1 if enable_depth else 0)

        @property

        def heading_enabled(self) -> bool:

            """Get or set the state of the heading overlay

            Requires Blunux version 1.7.60 or newer.

            """

            self._parent_drone._verify_required_blunux_version("1.7.60")

            return bool(self._get_named_overlay_parameters().heading_enabled)

        @heading_enabled.setter

        def heading_enabled(self, enable_heading: bool):

            self._parent_drone._verify_required_blunux_version("1.7.60")

            self._parent_drone._tcp_client.set_overlay_heading_enabled(1 if enable_heading else 0)

        @property

        def tilt_enabled(self) -> bool:

            """Get or set the state of the tilt overlay

            Requires Blunux version 1.7.60 or newer.

            """

            self._parent_drone._verify_required_blunux_version("1.7.60")

            return bool(self._get_named_overlay_parameters().tilt_enabled)

        @tilt_enabled.setter

        def tilt_enabled(self, enable_tilt: bool):

            self._parent_drone._verify_required_blunux_version("1.7.60")

            self._parent_drone._tcp_client.set_overlay_tilt_enabled(1 if enable_tilt else 0)

        @property

        def date_enabled(self) -> bool:

            """Get or set the state of the date overlay

            Requires Blunux version 1.7.60 or newer.

            """

            self._parent_drone._verify_required_blunux_version("1.7.60")

            return bool(self._get_named_overlay_parameters().date_enabled)

        @date_enabled.setter

        def date_enabled(self, enable_date: bool):

            self._parent_drone._verify_required_blunux_version("1.7.60")

            self._parent_drone._tcp_client.set_overlay_date_enabled(1 if enable_date else 0)

        @property

        def logo(self) -> LogoOverlay:

            """Get or set logo overlay selection

            Needs to be set to an instance of the `LogoOverlay` class, if not a RuntimeWarning is

            raised.

            Requires Blunux version 1.8.72 or newer.

            """

            self._parent_drone._verify_required_blunux_version("1.8.72")

            return LogoOverlay(self._get_named_overlay_parameters().logo_index)

        @logo.setter

        def logo(self, logo_index: LogoOverlay):

            self._parent_drone._verify_required_blunux_version("1.8.72")

            if not isinstance(logo_index, LogoOverlay):

                warnings.warn("Invalid logo index, ignoring", RuntimeWarning)

            elif logo_index.value not in range(3):

                warnings.warn("Logo index out of range, ignoring", RuntimeWarning)

            else:

                self._parent_drone._tcp_client.set_overlay_logo_index(logo_index.value)

        @property

        def depth_unit(self) -> DepthUnitOverlay:

            """Get or set the depth unit for the overlay

            Needs to be set to an instance of the `DepthUnitOverlay` class, if not a RuntimeWarning is

            raised.

            Requires Blunux version 1.7.60 or newer.

            """

            self._parent_drone._verify_required_blunux_version("1.7.60")

            return DepthUnitOverlay(self._get_named_overlay_parameters().depth_unit)

        @depth_unit.setter

        def depth_unit(self, unit_index: DepthUnitOverlay):

            self._parent_drone._verify_required_blunux_version("1.7.60")

            if not isinstance(unit_index, DepthUnitOverlay):

                warnings.warn("Invalid depth unit index, ignoring", RuntimeWarning)

            elif unit_index.value not in range(2):

                warnings.warn("Depth unit index out of range, ignoring", RuntimeWarning)

            else:

                self._parent_drone._tcp_client.set_overlay_depth_unit(unit_index.value)

        @property

        def temperature_unit(self) -> TemperatureUnitOverlay:

            """Get or set the temperature unit for the overlay

            Needs to be set to an instance of the `TemperatureUnitOverlay` class, if not a

            RuntimeWarning is raised.

            Requires Blunux version 1.7.60 or newer.

            """

            self._parent_drone._verify_required_blunux_version("1.7.60")

            return TemperatureUnitOverlay(self._get_named_overlay_parameters().temperature_unit)

        @temperature_unit.setter

        def temperature_unit(self, unit_index: TemperatureUnitOverlay):

            self._parent_drone._verify_required_blunux_version("1.7.60")

            if not isinstance(unit_index, TemperatureUnitOverlay):

                warnings.warn("Invalid temperature unit index, ignoring", RuntimeWarning)

            elif unit_index.value not in range(2):

                warnings.warn("Temperature unit index out of range, ignoring", RuntimeWarning)

            else:

                self._parent_drone._tcp_client.set_overlay_temperature_unit(unit_index.value)

        @property

        def timezone_offset(self) -> int:

            """Get or set the timezone offset for the overlay

            Set to the number of minutes (either positive or negative) the timestamp should be offset.

            Requires Blunux version 1.7.60 or newer.

            """

            self._parent_drone._verify_required_blunux_version("1.7.60")

            return self._get_named_overlay_parameters().tz_offset

        @timezone_offset.setter

        def timezone_offset(self, offset: int):

            self._parent_drone._verify_required_blunux_version("1.7.60")

            self._parent_drone._tcp_client.set_overlay_tz_offset(offset)

        @property

        def margin_width(self) -> int:

            """Get or set the margin width for the overlay

            The amount of pixels to use as margin on the right and left side of the overlay. Needs to

            be a positive integer.

            Requires Blunux version 1.7.60 or newer.

            """

            self._parent_drone._verify_required_blunux_version("1.7.60")

            return self._get_named_overlay_parameters().margin_width

        @margin_width.setter

        def margin_width(self, width: int):

            self._parent_drone._verify_required_blunux_version("1.7.60")

            if width < 0:

                warnings.warn("Invalid margin width, ignoring", RuntimeWarning)

            else:

                self._parent_drone._tcp_client.set_overlay_margin_width(width)

        @property

        def margin_height(self) -> int:

            """Get or set the margin height for the overlay

            The amount of pixels to use as margin on the top and bottom side of the overlay. Needs to be

            a positive integer.

            Requires Blunux version 1.7.60 or newer.

            """

            self._parent_drone._verify_required_blunux_version("1.7.60")

            return self._get_named_overlay_parameters().margin_height

        @margin_height.setter

        def margin_height(self, height: int):

            self._parent_drone._verify_required_blunux_version("1.7.60")

            if height < 0:

                warnings.warn("Invalid margin height, ignoring", RuntimeWarning)

            else:

                self._parent_drone._tcp_client.set_overlay_margin_height(height)

        @property

        def font_size(self) -> FontSizeOverlay:

            """Get or set the font size for the overlay

            Needs to be an instance of the `FontSizeOverlay` class, if not a RuntimeWarning is raised.

            Requires Blunux version 1.7.60 or newer.

            """

            self._parent_drone._verify_required_blunux_version("1.7.60")

            return FontSizeOverlay(self._get_named_overlay_parameters().font_size)

        @font_size.setter

        def font_size(self, size: FontSizeOverlay):

            self._parent_drone._verify_required_blunux_version("1.7.60")

            if not isinstance(size, FontSizeOverlay):

                warnings.warn("Invalid font size, ignoring", RuntimeWarning)

            elif size.value not in range(15, 41):

                warnings.warn("Font size out of range, ignoring", RuntimeWarning)

            else:

                self._parent_drone._tcp_client.set_overlay_font_size(size.value)

        @property

        def title(self) -> str:

            """Get or set the title for the overlay

            The title needs to be a string of only ASCII characters with a maximum length of 63

            characters. If a longer title is passed it will be truncated, and a RuntimeWarning is

            raised.

            Set to an empty string to disable title.

            Requires Blunux version 1.7.60 or newer.

            """

            self._parent_drone._verify_required_blunux_version("1.7.60")

            return self._get_named_overlay_parameters().title.decode("utf-8").rstrip("\x00")

        @title.setter

        def title(self, input_title: str):

            self._parent_drone._verify_required_blunux_version("1.7.60")

            new_title = input_title

            if len(input_title) > 63:

                warnings.warn("Too long title, truncating to 63 characters", RuntimeWarning)

                new_title = new_title[:63]

            try:

                encoded_title = bytes(new_title, "ascii")

            except UnicodeEncodeError:

                warnings.warn("Title can only contain ASCII characters, ignoring", RuntimeWarning)

                return

            self._parent_drone._tcp_client.set_overlay_title(encoded_title + b"\x00")

        @property

        def subtitle(self) -> str:

            """Get or set the subtitle for the overlay

            The subtitle needs to be a string of only ASCII characters with a maximum length of 63

            characters. If a longer subtitle is passed it will be truncated, and a RuntimeWarning is

            raised.

            Set to an empty string to disable the subtitle.

            Requires Blunux version 1.7.60 or newer.

            """

            self._parent_drone._verify_required_blunux_version("1.7.60")

            return self._get_named_overlay_parameters().subtitle.decode("utf-8").rstrip("\x00")

        @subtitle.setter

        def subtitle(self, input_subtitle: str):

            self._parent_drone._verify_required_blunux_version("1.7.60")

            new_subtitle = input_subtitle

            if len(input_subtitle) > 63:

                warnings.warn("Too long subtitle, truncating to 63 characters", RuntimeWarning)

                new_subtitle = new_subtitle[:63]

            try:

                encoded_subtitle = bytes(new_subtitle, "ascii")

            except UnicodeEncodeError:

                warnings.warn("Subtitle can only contain ASCII characters, ignoring", RuntimeWarning)

                return

            self._parent_drone._tcp_client.set_overlay_subtitle(encoded_subtitle + b"\x00")

        @property

        def date_format(self) -> str:

            """Get or set the format string for the time displayed in the overlay

            Must be a string containing only ASCII characters, with a max length of 63 characters.

            The format codes are defined by the C89 standard, see

            https://docs.python.org/3/library/datetime.html#strftime-and-strptime-format-codes

            for an overview of the available codes.

            """

            self._parent_drone._verify_required_blunux_version("1.7.60")

            return self._get_named_overlay_parameters().date_format.decode("utf-8").rstrip("\x00")

        @date_format.setter

        def date_format(self, input_format_str: str):

            self._parent_drone._verify_required_blunux_version("1.7.60")

            format_str = input_format_str

            if len(format_str) > 63:

                warnings.warn(

                    "Too long date format string, truncating to 63 characters", RuntimeWarning

                )

                format_str = format_str[:63]

            try:

                encoded_format_str = bytes(format_str, "ascii")

            except UnicodeEncodeError:

                warnings.warn(

                    "Date format string can only contain ASCII characters, ignoring", RuntimeWarning

                )

                return

            self._parent_drone._tcp_client.set_overlay_date_format(encoded_format_str + b"\x00")

        def upload_logo(self, path_to_logo: str):

            """Upload user selectable logo for watermarking videos and pictures

            Set the logo-property to `LogoOverlay.CUSTOM` to enable this logo.

            Allowed filetype: JPG or PNG.

            Max resolution: 2000 px.

            Max file size: 5 MB.

            Requires Blunux version 1.8.72 or newer.

            *Exceptions*:

            * `requests.exceptions.HTTPError` : Status code 400 for invalid files

            * `requests.exceptions.ConnectTimeout` : If unable to create a connection within 1s

            """

            self._parent_drone._verify_required_blunux_version("1.8.72")

            with open(path_to_logo, "rb") as f:

                url = f"http://{self._parent_drone._ip}/asset/logo"

                files = {"image": f}

                response = requests.post(url, files=files, timeout=1)

            response.raise_for_status()

        def download_logo(self, output_directory="."):

            """Download the original user uploaded logo (PNG or JPG)

            Select the download directory with the output_directory parameter.

            *Exceptions*:

            * `requests.exceptions.HTTPError` : If no custom logo is uploaded.

            * `requests.exceptions.ConnectTimeout` : If unable to create a connection within 1s

            """

            self._parent_drone._verify_required_blunux_version("1.8.72")

            response = requests.get(f"http://{self._parent_drone._ip}/asset/logo", timeout=1)

            response.raise_for_status()

            filename = re.findall('filename="(.+)"', response.headers["Content-Disposition"])[0]

            with open(f"{output_directory}/{filename}", "wb") as f:

                f.write(response.content)

        def delete_logo(self):

            """Delete the user uploaded logo from the drone

            *Exceptions*:

            * `requests.exceptions.HTTPError` : If an error occurs during deletion

            * `requests.exceptions.ConnectTimeout` : If unable to create a connection within 1s

            """

            self._parent_drone._verify_required_blunux_version("1.8.72")

            response = requests.delete(f"http://{self._parent_drone._ip}/asset/logo", timeout=1)

            response.raise_for_status()

#### Instance variables

    date_enabled

Get or set the state of the date overlay

Requires Blunux version 1.7.60 or newer.

    date_format

Get or set the format string for the time displayed in the overlay

Must be a string containing only ASCII characters, with a max length of 63 characters.

The format codes are defined by the C89 standard, see https://docs.python.org/3/library/datetime.html#strftime-and-strptime-format-codes for an overview of the available codes.

    depth_enabled

Get or set the state of the depth overlay

Requires Blunux version 1.7.60 or newer.

    depth_unit

Get or set the depth unit for the overlay

Needs to be set to an instance of the `DepthUnitOverlay` class, if not a RuntimeWarning is raised.

Requires Blunux version 1.7.60 or newer.

    font_size

Get or set the font size for the overlay

Needs to be an instance of the `FontSizeOverlay` class, if not a RuntimeWarning is raised.

Requires Blunux version 1.7.60 or newer.

    heading_enabled

Get or set the state of the heading overlay

Requires Blunux version 1.7.60 or newer.

    logo

Get or set logo overlay selection

Needs to be set to an instance of the `LogoOverlay` class, if not a RuntimeWarning is raised.

Requires Blunux version 1.8.72 or newer.

    margin_height

Get or set the margin height for the overlay

The amount of pixels to use as margin on the top and bottom side of the overlay. Needs to be a positive integer.

Requires Blunux version 1.7.60 or newer.

    margin_width

Get or set the margin width for the overlay

The amount of pixels to use as margin on the right and left side of the overlay. Needs to be a positive integer.

Requires Blunux version 1.7.60 or newer.

    subtitle

Get or set the subtitle for the overlay

The subtitle needs to be a string of only ASCII characters with a maximum length of 63 characters. If a longer subtitle is passed it will be truncated, and a RuntimeWarning is raised.

Set to an empty string to disable the subtitle.

Requires Blunux version 1.7.60 or newer.

    temperature_enabled

Get or set the state of the temperature overlay

Requires Blunux version 1.7.60 or newer.

    temperature_unit

Get or set the temperature unit for the overlay

Needs to be set to an instance of the `TemperatureUnitOverlay` class, if not a RuntimeWarning is raised.

Requires Blunux version 1.7.60 or newer.

    tilt_enabled

Get or set the state of the tilt overlay

Requires Blunux version 1.7.60 or newer.

    timezone_offset

Get or set the timezone offset for the overlay

Set to the number of minutes (either positive or negative) the timestamp should be offset.

Requires Blunux version 1.7.60 or newer.

    title

Get or set the title for the overlay

The title needs to be a string of only ASCII characters with a maximum length of 63 characters. If a longer title is passed it will be truncated, and a RuntimeWarning is raised.

Set to an empty string to disable title.

Requires Blunux version 1.7.60 or newer.

#### Methods

#### delete_logo

    def delete_logo(
        self
    )

Delete the user uploaded logo from the drone

Exceptions:

- `requests.exceptions.HTTPError` : If an error occurs during deletion

- `requests.exceptions.ConnectTimeout` : If unable to create a connection within 1s

View Source

        def delete_logo(self):

            """Delete the user uploaded logo from the drone

            *Exceptions*:

            * `requests.exceptions.HTTPError` : If an error occurs during deletion

            * `requests.exceptions.ConnectTimeout` : If unable to create a connection within 1s

            """

            self._parent_drone._verify_required_blunux_version("1.8.72")

            response = requests.delete(f"http://{self._parent_drone._ip}/asset/logo", timeout=1)

            response.raise_for_status()

#### download_logo

    def download_logo(
        self,
        output_directory='.'
    )

Download the original user uploaded logo (PNG or JPG)

Select the download directory with the output_directory parameter.

Exceptions:

- `requests.exceptions.HTTPError` : If no custom logo is uploaded.

- `requests.exceptions.ConnectTimeout` : If unable to create a connection within 1s

View Source

        def download_logo(self, output_directory="."):

            """Download the original user uploaded logo (PNG or JPG)

            Select the download directory with the output_directory parameter.

            *Exceptions*:

            * `requests.exceptions.HTTPError` : If no custom logo is uploaded.

            * `requests.exceptions.ConnectTimeout` : If unable to create a connection within 1s

            """

            self._parent_drone._verify_required_blunux_version("1.8.72")

            response = requests.get(f"http://{self._parent_drone._ip}/asset/logo", timeout=1)

            response.raise_for_status()

            filename = re.findall('filename="(.+)"', response.headers["Content-Disposition"])[0]

            with open(f"{output_directory}/{filename}", "wb") as f:

                f.write(response.content)

#### upload_logo

    def upload_logo(
        self,
        path_to_logo: 'str'
    )

Upload user selectable logo for watermarking videos and pictures

Set the logo-property to `LogoOverlay.CUSTOM` to enable this logo.

Allowed filetype: JPG or PNG. Max resolution: 2000 px. Max file size: 5 MB.

Requires Blunux version 1.8.72 or newer.

Exceptions:

- `requests.exceptions.HTTPError` : Status code 400 for invalid files

- `requests.exceptions.ConnectTimeout` : If unable to create a connection within 1s

View Source

        def upload_logo(self, path_to_logo: str):

            """Upload user selectable logo for watermarking videos and pictures

            Set the logo-property to `LogoOverlay.CUSTOM` to enable this logo.

            Allowed filetype: JPG or PNG.

            Max resolution: 2000 px.

            Max file size: 5 MB.

            Requires Blunux version 1.8.72 or newer.

            *Exceptions*:

            * `requests.exceptions.HTTPError` : Status code 400 for invalid files

            * `requests.exceptions.ConnectTimeout` : If unable to create a connection within 1s

            """

            self._parent_drone._verify_required_blunux_version("1.8.72")

            with open(path_to_logo, "rb") as f:

                url = f"http://{self._parent_drone._ip}/asset/logo"

                files = {"image": f}

                response = requests.post(url, files=files, timeout=1)

            response.raise_for_status()

### TemperatureUnitOverlay

    class TemperatureUnitOverlay(
        /,
        *args,
        **kwargs
    )

View Source

    class TemperatureUnitOverlay(Enum):

        CELSIUS = 0

        FAHRENHEIT = 1

#### Ancestors (in MRO)

- enum.Enum

#### Class variables

    CELSIUS

    FAHRENHEIT

    name

    value

### Tilt

    class Tilt(
        parent_drone: 'Drone'
    )

View Source

    class Tilt:

        @staticmethod

        def _tilt_angle_from_debug_flags(flags: int) -> float:

            """Helper function for decoding tilt angle from debug flags

            The tilt angle is encoded as an int8, with 0 at 0 degrees, and each increment representing

            0.5 degrees in either direction. A positive angle is upwards, and negative is downwards.

            """

            TILT_ANGLE_MASK = 0x0000FF0000000000

            TILT_ANGLE_OFFSET = 40

            tilt_angle_array = np.array(

                np.right_shift(np.bitwise_and(flags, TILT_ANGLE_MASK), TILT_ANGLE_OFFSET),

                dtype=[("tilt_angle", np.int8)],

            ).astype([("tilt_angle", float)])

            return tilt_angle_array["tilt_angle"] / 2

        @staticmethod

        def _tilt_stabilization_status_from_debug_flags(flags: int) -> bool:

            """Helper function for decoding tilt stabilization status from debug flags"""

            TILT_STABILIZATION_MASK = 0x100

            return bool(flags & TILT_STABILIZATION_MASK)

        def __init__(self, parent_drone: Drone):

            self._parent_drone = parent_drone

        def _verify_tilt_in_features(self):

            """Checks that the connected drone has the tilt feature

            Raises a RuntimeError if it does not.

            """

            if "tilt" not in self._parent_drone.features:

                raise RuntimeError("The connected drone does not support tilting the camera.")

        def set_speed(self, speed: float):

            """Set the speed and direction of the camera tilt

            *Arguments*:

            * speed (float): Speed and direction of the tilt. 1 is max speed up, -1 is max speed down.

            Requires a drone with the tilt feature, and software version 1.5 or newer.

            A RuntimeError is raised if either of those requirements are not met.

            """

            self._parent_drone._verify_required_blunux_version("1.5")

            self._verify_tilt_in_features()

            # The tilt command is grouped together with the thruster commands, so to avoid messing with

            # the thruster setpoint while tilting we need to get the current setpoint and send it with

            # the tilt command.

            with self._parent_drone.motion.thruster_lock:

                thruster_setpoints = self._parent_drone.motion.current_thruster_setpoints.values()

                self._parent_drone._tcp_client.motion_input_tilt(*thruster_setpoints, 0, 0, speed)

        @property

        def angle(self) -> float:

            """Return the current angle of the camera tilt

            Requires a drone with the tilt feature, and software version 1.5 or newer.

            A RuntimeError is raised if either of those requirements are not met.

            """

            self._parent_drone._verify_required_blunux_version("1.5")

            self._verify_tilt_in_features()

            debug_flags = self._parent_drone._state_watcher.general_state["debug_flags"]

            return self._tilt_angle_from_debug_flags(debug_flags)

        @property

        def stabilization_enabled(self) -> bool:

            """Get the state of active camera stabilization

            Use the `toggle_stabilization` method to turn stabilization on or off

            *Returns*:

            * Current state of active camera stabilization (bool)

            """

            self._parent_drone._verify_required_blunux_version("1.6.42")

            self._verify_tilt_in_features()

            debug_flags = self._parent_drone._state_watcher.general_state["debug_flags"]

            return self._tilt_stabilization_status_from_debug_flags(debug_flags)

        def toggle_stabilization(self):

            """Toggle active camera stabilization on or off

            Requires a drone with the tilt feature, and Blunux version 1.6.42 or newer.

            A RuntimeError is raised if either of those requirements are not met.

            """

            self._parent_drone._verify_required_blunux_version("1.6.42")

            self._verify_tilt_in_features()

            self._parent_drone._tcp_client.toggle_tilt_stabilization()

#### Instance variables

    angle

Return the current angle of the camera tilt

Requires a drone with the tilt feature, and software version 1.5 or newer. A RuntimeError is raised if either of those requirements are not met.

    stabilization_enabled

Get the state of active camera stabilization

Use the `toggle_stabilization` method to turn stabilization on or off

Returns:

- Current state of active camera stabilization (bool)

#### Methods

#### set_speed

    def set_speed(
        self,
        speed: 'float'
    )

Set the speed and direction of the camera tilt

Arguments:

- speed (float): Speed and direction of the tilt. 1 is max speed up, -1 is max speed down.

Requires a drone with the tilt feature, and software version 1.5 or newer. A RuntimeError is raised if either of those requirements are not met.

View Source

        def set_speed(self, speed: float):

            """Set the speed and direction of the camera tilt

            *Arguments*:

            * speed (float): Speed and direction of the tilt. 1 is max speed up, -1 is max speed down.

            Requires a drone with the tilt feature, and software version 1.5 or newer.

            A RuntimeError is raised if either of those requirements are not met.

            """

            self._parent_drone._verify_required_blunux_version("1.5")

            self._verify_tilt_in_features()

            # The tilt command is grouped together with the thruster commands, so to avoid messing with

            # the thruster setpoint while tilting we need to get the current setpoint and send it with

            # the tilt command.

            with self._parent_drone.motion.thruster_lock:

                thruster_setpoints = self._parent_drone.motion.current_thruster_setpoints.values()

                self._parent_drone._tcp_client.motion_input_tilt(*thruster_setpoints, 0, 0, speed)

#### toggle_stabilization

    def toggle_stabilization(
        self
    )

Toggle active camera stabilization on or off

Requires a drone with the tilt feature, and Blunux version 1.6.42 or newer. A RuntimeError is raised if either of those requirements are not met.

View Source

        def toggle_stabilization(self):

            """Toggle active camera stabilization on or off

            Requires a drone with the tilt feature, and Blunux version 1.6.42 or newer.

            A RuntimeError is raised if either of those requirements are not met.

            """

            self._parent_drone._verify_required_blunux_version("1.6.42")

            self._verify_tilt_in_features()

            self._parent_drone._tcp_client.toggle_tilt_stabilization()