"""
Project generated by builder 0.7.2
"""
import logging
from sys import version_info
from ctypes import CDLL, Structure, Array, CFUNCTYPE, byref, create_string_buffer, addressof, cast
from ctypes import c_ubyte, c_byte, c_ushort, c_short, c_uint, c_int, c_ulonglong, c_longlong, c_float, \
     c_void_p, c_char_p, c_wchar_p, c_size_t
from ctypes.util import find_library
import atexit
try:
    from typing import overload, Union, Sequence, Optional
except ImportError:
    def overload(method):
        return method
    class _GenericTypeMeta(type):
        def __getitem__(self, _):
            return None
    class Union(metaclass=_GenericTypeMeta):
        pass
    class Sequence(metaclass=_GenericTypeMeta):
        pass
    class Optional(metaclass=_GenericTypeMeta):
        pass
urpc_builder_version_major = 0
urpc_builder_version_minor = 7
urpc_builder_version_bugfix = 2
urpc_builder_version_suffix = ""
urpc_builder_version = "0.7.2"
_Ok = 0
_Error = -1
_NotImplemented = -2
_ValueError = -3
_NoDevice = -4
_DeviceUndefined = -1
class _IterableStructure(Structure):
    def __iter__(self):
        return (getattr(self, n) for n, t in self._fields_)
def _validate_call(result):
    if result == _ValueError:
        raise ValueError()
    elif result == _NotImplemented:
        raise NotImplementedError()
    elif result != _Ok:
        raise RuntimeError()
def _normalize_arg(value, desired_ctype):
    from collections import Sequence
    if isinstance(value, desired_ctype):
        return value
    elif issubclass(desired_ctype, Array) and isinstance(value, Sequence):
        member_type = desired_ctype._type_
        if desired_ctype._length_ < len(value):
            raise ValueError()
        if issubclass(member_type, c_ubyte) and isinstance(value, bytes):
            return desired_ctype.from_buffer_copy(value)
        elif issubclass(member_type, c_ubyte) and isinstance(value, bytearray):
            return desired_ctype.from_buffer(value)
        else:
            return desired_ctype(*value)
    else:
        return desired_ctype(value)


def _load_lib():
    from platform import system
    lib = None
    os_kind = system().lower()
    if os_kind == "windows":
        lib = CDLL("ivm.dll")
    elif os_kind == "darwin":
        lib = CDLL("libivm.dylib")
    elif os_kind == "freebsd" or "linux" in os_kind:
        lib = CDLL("libivm.so")
    else:
        raise RuntimeError("unexpected OS")

    return lib

_lib = _load_lib()


# Hack to prevent auto-conversion to native Python int
class _device_t(c_int):
    def from_param(self, *args):
        return self
_lib.ivm_open_device.restype = _device_t


_logger = logging.getLogger(__name__)
@CFUNCTYPE(None, c_int, c_wchar_p, c_void_p)
def _logging_callback(loglevel, message, user_data):
    if loglevel == 0x01:
        _logger.error(message)
    elif loglevel == 0x02:
        _logger.warning(message)
    elif loglevel == 0x03:
        _logger.info(message)
    elif loglevel == 0x04:
        _logger.debug(message)
_lib.ivm_set_logging_callback(_logging_callback)
atexit.register(lambda: _lib.ivm_set_logging_callback(None))


def reset_locks():
    _validate_call(_lib.ivm_reset_locks())


def fix_usbser_sys():
    _validate_call(_lib.ivm_fix_usbser_sys())


class IvmDeviceHandle:
    class GetMeasurementRequest(_IterableStructure):
        _fields_ = (
            ("_frame_number", c_ushort),
        )

        class FrameNumber(int):
            FRAME_SIZE = 25

            @property
            def frame_size(self) -> int:
                return self & self.FRAME_SIZE                

        @property
        def frame_number(self) -> FrameNumber:
            return self.FrameNumber(self._frame_number)

        @frame_number.setter
        def frame_number(self, value: Union[int, c_ushort]) -> None:
            self._frame_number = _normalize_arg(value, c_ushort)

    class GetMeasurementResponse(_IterableStructure):
        _fields_ = (
            ("_voltage", c_float*25),
            ("_current", c_float*25),
        )

        @property
        def voltage(self) -> c_float*25:
            return self._voltage


        @voltage.setter
        def voltage(self, value: Union[Sequence[float], c_float*25]) -> None:
            self._voltage = _normalize_arg(value, c_float*25)

        @property
        def current(self) -> c_float*25:
            return self._current


        @current.setter
        def current(self, value: Union[Sequence[float], c_float*25]) -> None:
            self._current = _normalize_arg(value, c_float*25)

    @overload
    def get_measurement(
            self,
            frame_number: Union[int, c_ushort],
            *,
            dst_buffer: Optional[GetMeasurementResponse]=None
    ) -> GetMeasurementResponse: pass

    @overload
    def get_measurement(
            self,
            src_buffer: GetMeasurementRequest,
            *,
            dst_buffer: Optional[GetMeasurementResponse]=None
    ) -> GetMeasurementResponse: pass

    def get_measurement(self, *args, **kwargs) -> GetMeasurementResponse:
        src_buffer = None
        if len(args) != 1 or not isinstance(args[0], self.GetMeasurementRequest):
            src_buffer = self.GetMeasurementRequest(
                frame_number=_normalize_arg(args[0], c_ushort)
            )
        else:
            src_buffer = args[0]
        dst_buffer = kwargs.get("dst_buffer", self.GetMeasurementResponse())
        _validate_call(_lib.ivm_get_measurement(self._handle, byref(src_buffer), byref(dst_buffer)))
        return dst_buffer

    class GetIdentityInformationResponse(_IterableStructure):
        _fields_ = (
            ("_manufacturer", c_ubyte*16),
            ("_product_name", c_ubyte*16),
            ("_controller_name", c_ubyte*16),
            ("_hardware_major", c_ubyte),
            ("_hardware_minor", c_ubyte),
            ("_hardware_bugfix", c_ushort),
            ("_bootloader_major", c_ubyte),
            ("_bootloader_minor", c_ubyte),
            ("_bootloader_bugfix", c_ushort),
            ("_firmware_major", c_ubyte),
            ("_firmware_minor", c_ubyte),
            ("_firmware_bugfix", c_ushort),
            ("_serial_number", c_uint),
            ("_reserved", c_ubyte*8),
        )

        @property
        def manufacturer(self) -> c_ubyte*16:
            return self._manufacturer


        @manufacturer.setter
        def manufacturer(self, value: Union[Sequence[int], c_ubyte*16]) -> None:
            self._manufacturer = _normalize_arg(value, c_ubyte*16)

        @property
        def product_name(self) -> c_ubyte*16:
            return self._product_name


        @product_name.setter
        def product_name(self, value: Union[Sequence[int], c_ubyte*16]) -> None:
            self._product_name = _normalize_arg(value, c_ubyte*16)

        @property
        def controller_name(self) -> c_ubyte*16:
            return self._controller_name


        @controller_name.setter
        def controller_name(self, value: Union[Sequence[int], c_ubyte*16]) -> None:
            self._controller_name = _normalize_arg(value, c_ubyte*16)

        @property
        def hardware_major(self) -> c_ubyte:
            return self._hardware_major


        @hardware_major.setter
        def hardware_major(self, value: Union[int, c_ubyte]) -> None:
            self._hardware_major = _normalize_arg(value, c_ubyte)

        @property
        def hardware_minor(self) -> c_ubyte:
            return self._hardware_minor


        @hardware_minor.setter
        def hardware_minor(self, value: Union[int, c_ubyte]) -> None:
            self._hardware_minor = _normalize_arg(value, c_ubyte)

        @property
        def hardware_bugfix(self) -> c_ushort:
            return self._hardware_bugfix


        @hardware_bugfix.setter
        def hardware_bugfix(self, value: Union[int, c_ushort]) -> None:
            self._hardware_bugfix = _normalize_arg(value, c_ushort)

        @property
        def bootloader_major(self) -> c_ubyte:
            return self._bootloader_major


        @bootloader_major.setter
        def bootloader_major(self, value: Union[int, c_ubyte]) -> None:
            self._bootloader_major = _normalize_arg(value, c_ubyte)

        @property
        def bootloader_minor(self) -> c_ubyte:
            return self._bootloader_minor


        @bootloader_minor.setter
        def bootloader_minor(self, value: Union[int, c_ubyte]) -> None:
            self._bootloader_minor = _normalize_arg(value, c_ubyte)

        @property
        def bootloader_bugfix(self) -> c_ushort:
            return self._bootloader_bugfix


        @bootloader_bugfix.setter
        def bootloader_bugfix(self, value: Union[int, c_ushort]) -> None:
            self._bootloader_bugfix = _normalize_arg(value, c_ushort)

        @property
        def firmware_major(self) -> c_ubyte:
            return self._firmware_major


        @firmware_major.setter
        def firmware_major(self, value: Union[int, c_ubyte]) -> None:
            self._firmware_major = _normalize_arg(value, c_ubyte)

        @property
        def firmware_minor(self) -> c_ubyte:
            return self._firmware_minor


        @firmware_minor.setter
        def firmware_minor(self, value: Union[int, c_ubyte]) -> None:
            self._firmware_minor = _normalize_arg(value, c_ubyte)

        @property
        def firmware_bugfix(self) -> c_ushort:
            return self._firmware_bugfix


        @firmware_bugfix.setter
        def firmware_bugfix(self, value: Union[int, c_ushort]) -> None:
            self._firmware_bugfix = _normalize_arg(value, c_ushort)

        @property
        def serial_number(self) -> c_uint:
            return self._serial_number


        @serial_number.setter
        def serial_number(self, value: Union[int, c_uint]) -> None:
            self._serial_number = _normalize_arg(value, c_uint)

        @property
        def reserved(self) -> c_ubyte*8:
            return self._reserved


        @reserved.setter
        def reserved(self, value: Union[Sequence[int], c_ubyte*8]) -> None:
            self._reserved = _normalize_arg(value, c_ubyte*8)

    def get_identity_information(self, **kwargs) -> GetIdentityInformationResponse:
        dst_buffer = kwargs.get("dst_buffer", self.GetIdentityInformationResponse())
        _validate_call(_lib.ivm_get_identity_information(self._handle, byref(dst_buffer)))
        return dst_buffer

    class StartAutocalibrationResponse(_IterableStructure):
        _fields_ = (
            ("_result", c_ubyte),
        )

        class Result(int):
            CALIBRATION_OK = 0

            @property
            def calibration_ok(self) -> int:
                return self & self.CALIBRATION_OK                

        @property
        def result(self) -> Result:
            return self.Result(self._result)

        @result.setter
        def result(self, value: Union[int, c_ubyte]) -> None:
            self._result = _normalize_arg(value, c_ubyte)

    def start_autocalibration(self, **kwargs) -> StartAutocalibrationResponse:
        dst_buffer = kwargs.get("dst_buffer", self.StartAutocalibrationResponse())
        _validate_call(_lib.ivm_start_autocalibration(self._handle, byref(dst_buffer)))
        return dst_buffer

    class GetStatusResponse(_IterableStructure):
        _fields_ = (
            ("_status", c_uint),
            ("_temp", c_short),
            ("_reserved", c_ubyte*48),
        )

        class Status(int):
            STATUS_OK = 0

            @property
            def status_ok(self) -> int:
                return self & self.STATUS_OK                

        @property
        def status(self) -> Status:
            return self.Status(self._status)

        @status.setter
        def status(self, value: Union[int, c_uint]) -> None:
            self._status = _normalize_arg(value, c_uint)

        @property
        def temp(self) -> c_short:
            return self._temp


        @temp.setter
        def temp(self, value: Union[int, c_short]) -> None:
            self._temp = _normalize_arg(value, c_short)

        @property
        def reserved(self) -> c_ubyte*48:
            return self._reserved


        @reserved.setter
        def reserved(self, value: Union[Sequence[int], c_ubyte*48]) -> None:
            self._reserved = _normalize_arg(value, c_ubyte*48)

    def get_status(self, **kwargs) -> GetStatusResponse:
        dst_buffer = kwargs.get("dst_buffer", self.GetStatusResponse())
        _validate_call(_lib.ivm_get_status(self._handle, byref(dst_buffer)))
        return dst_buffer

    def start_measurement(self) -> None:
        _validate_call(_lib.ivm_start_measurement(self._handle))

    class CheckMeasurementStatusResponse(_IterableStructure):
        _fields_ = (
            ("_ready_status", c_ubyte),
            ("_reserved", c_ubyte*15),
        )

        class ReadyStatus(int):
            MEASUREMENT_NOT_COMPLETE = 0
            MEASUREMENT_COMPLETE = 1

            @property
            def measurement_not_complete(self) -> int:
                return self & self.MEASUREMENT_NOT_COMPLETE                

            @property
            def measurement_complete(self) -> int:
                return self & self.MEASUREMENT_COMPLETE                

        @property
        def ready_status(self) -> ReadyStatus:
            return self.ReadyStatus(self._ready_status)

        @ready_status.setter
        def ready_status(self, value: Union[int, c_ubyte]) -> None:
            self._ready_status = _normalize_arg(value, c_ubyte)

        @property
        def reserved(self) -> c_ubyte*15:
            return self._reserved


        @reserved.setter
        def reserved(self, value: Union[Sequence[int], c_ubyte*15]) -> None:
            self._reserved = _normalize_arg(value, c_ubyte*15)

    def check_measurement_status(self, **kwargs) -> CheckMeasurementStatusResponse:
        dst_buffer = kwargs.get("dst_buffer", self.CheckMeasurementStatusResponse())
        _validate_call(_lib.ivm_check_measurement_status(self._handle, byref(dst_buffer)))
        return dst_buffer

    class GetMeasurementRawRequest(_IterableStructure):
        _fields_ = (
            ("_frame", c_ushort),
        )

        @property
        def frame(self) -> c_ushort:
            return self._frame


        @frame.setter
        def frame(self, value: Union[int, c_ushort]) -> None:
            self._frame = _normalize_arg(value, c_ushort)

    class GetMeasurementRawResponse(_IterableStructure):
        _fields_ = (
            ("_adc_high_code", c_ushort*25),
            ("_adc_low_code", c_ushort*25),
        )

        @property
        def adc_high_code(self) -> c_ushort*25:
            return self._adc_high_code


        @adc_high_code.setter
        def adc_high_code(self, value: Union[Sequence[int], c_ushort*25]) -> None:
            self._adc_high_code = _normalize_arg(value, c_ushort*25)

        @property
        def adc_low_code(self) -> c_ushort*25:
            return self._adc_low_code


        @adc_low_code.setter
        def adc_low_code(self, value: Union[Sequence[int], c_ushort*25]) -> None:
            self._adc_low_code = _normalize_arg(value, c_ushort*25)

    @overload
    def get_measurement_raw(
            self,
            frame: Union[int, c_ushort],
            *,
            dst_buffer: Optional[GetMeasurementRawResponse]=None
    ) -> GetMeasurementRawResponse: pass

    @overload
    def get_measurement_raw(
            self,
            src_buffer: GetMeasurementRawRequest,
            *,
            dst_buffer: Optional[GetMeasurementRawResponse]=None
    ) -> GetMeasurementRawResponse: pass

    def get_measurement_raw(self, *args, **kwargs) -> GetMeasurementRawResponse:
        src_buffer = None
        if len(args) != 1 or not isinstance(args[0], self.GetMeasurementRawRequest):
            src_buffer = self.GetMeasurementRawRequest(
                frame=_normalize_arg(args[0], c_ushort)
            )
        else:
            src_buffer = args[0]
        dst_buffer = kwargs.get("dst_buffer", self.GetMeasurementRawResponse())
        _validate_call(_lib.ivm_get_measurement_raw(self._handle, byref(src_buffer), byref(dst_buffer)))
        return dst_buffer

    class GetDeviceRankResponse(_IterableStructure):
        _fields_ = (
            ("_rank", c_uint),
            ("_reserved0", c_ubyte*128),
        )

        class Rank(int):
            RANKING_NOT_SUPPORTED = 0
            RANK_PRIMARY = 1

            @property
            def ranking_not_supported(self) -> int:
                return self & self.RANKING_NOT_SUPPORTED                

            @property
            def rank_primary(self) -> int:
                return self & self.RANK_PRIMARY                

        @property
        def rank(self) -> Rank:
            return self.Rank(self._rank)

        @rank.setter
        def rank(self, value: Union[int, c_uint]) -> None:
            self._rank = _normalize_arg(value, c_uint)

        @property
        def reserved0(self) -> c_ubyte*128:
            return self._reserved0


        @reserved0.setter
        def reserved0(self, value: Union[Sequence[int], c_ubyte*128]) -> None:
            self._reserved0 = _normalize_arg(value, c_ubyte*128)

    def get_device_rank(self, **kwargs) -> GetDeviceRankResponse:
        dst_buffer = kwargs.get("dst_buffer", self.GetDeviceRankResponse())
        _validate_call(_lib.ivm_get_device_rank(self._handle, byref(dst_buffer)))
        return dst_buffer

    class MeasurementSettingsRequest(_IterableStructure):
        _fields_ = (
            ("_sampling_rate", c_float),
            ("_probe_signal_frequency", c_float),
            ("_number_points", c_uint),
            ("_number_charge_points", c_uint),
            ("_max_voltage", c_float),
            ("_reserved0", c_ubyte*4),
            ("_current_sensor_mode", c_uint),
            ("_output_mode", c_ubyte),
            ("_reserved1", c_ubyte*19),
        )

        @property
        def sampling_rate(self) -> c_float:
            return self._sampling_rate


        @sampling_rate.setter
        def sampling_rate(self, value: Union[float, c_float]) -> None:
            self._sampling_rate = _normalize_arg(value, c_float)

        @property
        def probe_signal_frequency(self) -> c_float:
            return self._probe_signal_frequency


        @probe_signal_frequency.setter
        def probe_signal_frequency(self, value: Union[float, c_float]) -> None:
            self._probe_signal_frequency = _normalize_arg(value, c_float)

        class NumberPoints(int):
            MIN_NUMBER_POINTS = 10
            MAX_NUMBER_POINTS = 1000

            @property
            def min_number_points(self) -> int:
                return self & self.MIN_NUMBER_POINTS                

            @property
            def max_number_points(self) -> int:
                return self & self.MAX_NUMBER_POINTS                

        @property
        def number_points(self) -> NumberPoints:
            return self.NumberPoints(self._number_points)

        @number_points.setter
        def number_points(self, value: Union[int, c_uint]) -> None:
            self._number_points = _normalize_arg(value, c_uint)

        @property
        def number_charge_points(self) -> c_uint:
            return self._number_charge_points


        @number_charge_points.setter
        def number_charge_points(self, value: Union[int, c_uint]) -> None:
            self._number_charge_points = _normalize_arg(value, c_uint)

        @property
        def max_voltage(self) -> c_float:
            return self._max_voltage


        @max_voltage.setter
        def max_voltage(self, value: Union[float, c_float]) -> None:
            self._max_voltage = _normalize_arg(value, c_float)

        @property
        def reserved0(self) -> c_ubyte*4:
            return self._reserved0


        @reserved0.setter
        def reserved0(self, value: Union[Sequence[int], c_ubyte*4]) -> None:
            self._reserved0 = _normalize_arg(value, c_ubyte*4)

        class CurrentSensorMode(int):
            CURRENT_SENSE_MODE_ISOLATED = 0
            CURRENT_SENSE_MODE_I_LOW = 1
            CURRENT_SENSE_MODE_I_MID = 2
            CURRENT_SENSE_MODE_I_HIGH = 3

            @property
            def current_sense_mode_isolated(self) -> int:
                return self & self.CURRENT_SENSE_MODE_ISOLATED                

            @property
            def current_sense_mode_i_low(self) -> int:
                return self & self.CURRENT_SENSE_MODE_I_LOW                

            @property
            def current_sense_mode_i_mid(self) -> int:
                return self & self.CURRENT_SENSE_MODE_I_MID                

            @property
            def current_sense_mode_i_high(self) -> int:
                return self & self.CURRENT_SENSE_MODE_I_HIGH                

        @property
        def current_sensor_mode(self) -> CurrentSensorMode:
            return self.CurrentSensorMode(self._current_sensor_mode)

        @current_sensor_mode.setter
        def current_sensor_mode(self, value: Union[int, c_uint]) -> None:
            self._current_sensor_mode = _normalize_arg(value, c_uint)

        class OutputMode(int):
            OUT_MODE_PROBE_SIGNAL_CONTINUOUS = 0
            OUT_MODE_GROUNDED_CONTINUOUS = 1
            OUT_MODE_PROBE_SIGNAL_WITH_GROUNDING = 2

            @property
            def out_mode_probe_signal_continuous(self) -> int:
                return self & self.OUT_MODE_PROBE_SIGNAL_CONTINUOUS                

            @property
            def out_mode_grounded_continuous(self) -> int:
                return self & self.OUT_MODE_GROUNDED_CONTINUOUS                

            @property
            def out_mode_probe_signal_with_grounding(self) -> int:
                return self & self.OUT_MODE_PROBE_SIGNAL_WITH_GROUNDING                

        @property
        def output_mode(self) -> OutputMode:
            return self.OutputMode(self._output_mode)

        @output_mode.setter
        def output_mode(self, value: Union[int, c_ubyte]) -> None:
            self._output_mode = _normalize_arg(value, c_ubyte)

        @property
        def reserved1(self) -> c_ubyte*19:
            return self._reserved1


        @reserved1.setter
        def reserved1(self, value: Union[Sequence[int], c_ubyte*19]) -> None:
            self._reserved1 = _normalize_arg(value, c_ubyte*19)

    MeasurementSettingsResponse = MeasurementSettingsRequest

    def get_measurement_settings(self, **kwargs) -> MeasurementSettingsResponse:
        dst_buffer = kwargs.get("dst_buffer", self.MeasurementSettingsResponse())
        _validate_call(_lib.ivm_get_measurement_settings(self._handle, byref(dst_buffer)))
        return dst_buffer

    @overload
    def set_measurement_settings(
            self,
            sampling_rate: Union[float, c_float],
            probe_signal_frequency: Union[float, c_float],
            number_points: Union[int, c_uint],
            number_charge_points: Union[int, c_uint],
            max_voltage: Union[float, c_float],
            reserved0: Union[Sequence[int], c_ubyte*4],
            current_sensor_mode: Union[int, c_uint],
            output_mode: Union[int, c_ubyte],
            reserved1: Union[Sequence[int], c_ubyte*19]
    ) -> None: pass

    @overload
    def set_measurement_settings(
            self,
            src_buffer: MeasurementSettingsRequest
    ) -> None: pass

    def set_measurement_settings(self, *args) -> None:
        src_buffer = None
        if len(args) != 1 or not isinstance(args[0], self.MeasurementSettingsRequest):
            src_buffer = self.MeasurementSettingsRequest(
                sampling_rate=_normalize_arg(args[0], c_float),
                probe_signal_frequency=_normalize_arg(args[1], c_float),
                number_points=_normalize_arg(args[2], c_uint),
                number_charge_points=_normalize_arg(args[3], c_uint),
                max_voltage=_normalize_arg(args[4], c_float),
                reserved0=_normalize_arg(args[5], c_ubyte*4),
                current_sensor_mode=_normalize_arg(args[6], c_uint),
                output_mode=_normalize_arg(args[7], c_ubyte),
                reserved1=_normalize_arg(args[8], c_ubyte*19)
            )
        else:
            src_buffer = args[0]
        _validate_call(_lib.ivm_set_measurement_settings(self._handle, byref(src_buffer)))

    class CalibrationSettingsRequest(_IterableStructure):
        _fields_ = (
            ("_reserved0", c_ubyte*8),
            ("_adc_mult", c_float),
            ("_adcv_offset", c_float),
            ("_current_sense1_mult", c_float),
            ("_current_sense1_offset", c_float),
            ("_current_sense2_mult", c_float),
            ("_current_sense2_offset", c_float),
            ("_current_sense3_mult", c_float),
            ("_current_sense3_offset", c_float),
            ("_reserved1", c_ubyte*72),
        )

        @property
        def reserved0(self) -> c_ubyte*8:
            return self._reserved0


        @reserved0.setter
        def reserved0(self, value: Union[Sequence[int], c_ubyte*8]) -> None:
            self._reserved0 = _normalize_arg(value, c_ubyte*8)

        @property
        def adc_mult(self) -> c_float:
            return self._adc_mult


        @adc_mult.setter
        def adc_mult(self, value: Union[float, c_float]) -> None:
            self._adc_mult = _normalize_arg(value, c_float)

        @property
        def adcv_offset(self) -> c_float:
            return self._adcv_offset


        @adcv_offset.setter
        def adcv_offset(self, value: Union[float, c_float]) -> None:
            self._adcv_offset = _normalize_arg(value, c_float)

        @property
        def current_sense1_mult(self) -> c_float:
            return self._current_sense1_mult


        @current_sense1_mult.setter
        def current_sense1_mult(self, value: Union[float, c_float]) -> None:
            self._current_sense1_mult = _normalize_arg(value, c_float)

        @property
        def current_sense1_offset(self) -> c_float:
            return self._current_sense1_offset


        @current_sense1_offset.setter
        def current_sense1_offset(self, value: Union[float, c_float]) -> None:
            self._current_sense1_offset = _normalize_arg(value, c_float)

        @property
        def current_sense2_mult(self) -> c_float:
            return self._current_sense2_mult


        @current_sense2_mult.setter
        def current_sense2_mult(self, value: Union[float, c_float]) -> None:
            self._current_sense2_mult = _normalize_arg(value, c_float)

        @property
        def current_sense2_offset(self) -> c_float:
            return self._current_sense2_offset


        @current_sense2_offset.setter
        def current_sense2_offset(self, value: Union[float, c_float]) -> None:
            self._current_sense2_offset = _normalize_arg(value, c_float)

        @property
        def current_sense3_mult(self) -> c_float:
            return self._current_sense3_mult


        @current_sense3_mult.setter
        def current_sense3_mult(self, value: Union[float, c_float]) -> None:
            self._current_sense3_mult = _normalize_arg(value, c_float)

        @property
        def current_sense3_offset(self) -> c_float:
            return self._current_sense3_offset


        @current_sense3_offset.setter
        def current_sense3_offset(self, value: Union[float, c_float]) -> None:
            self._current_sense3_offset = _normalize_arg(value, c_float)

        @property
        def reserved1(self) -> c_ubyte*72:
            return self._reserved1


        @reserved1.setter
        def reserved1(self, value: Union[Sequence[int], c_ubyte*72]) -> None:
            self._reserved1 = _normalize_arg(value, c_ubyte*72)

    CalibrationSettingsResponse = CalibrationSettingsRequest

    def get_calibration_settings(self, **kwargs) -> CalibrationSettingsResponse:
        dst_buffer = kwargs.get("dst_buffer", self.CalibrationSettingsResponse())
        _validate_call(_lib.ivm_get_calibration_settings(self._handle, byref(dst_buffer)))
        return dst_buffer

    @overload
    def set_calibration_settings(
            self,
            reserved0: Union[Sequence[int], c_ubyte*8],
            adc_mult: Union[float, c_float],
            adcv_offset: Union[float, c_float],
            current_sense1_mult: Union[float, c_float],
            current_sense1_offset: Union[float, c_float],
            current_sense2_mult: Union[float, c_float],
            current_sense2_offset: Union[float, c_float],
            current_sense3_mult: Union[float, c_float],
            current_sense3_offset: Union[float, c_float],
            reserved1: Union[Sequence[int], c_ubyte*72]
    ) -> None: pass

    @overload
    def set_calibration_settings(
            self,
            src_buffer: CalibrationSettingsRequest
    ) -> None: pass

    def set_calibration_settings(self, *args) -> None:
        src_buffer = None
        if len(args) != 1 or not isinstance(args[0], self.CalibrationSettingsRequest):
            src_buffer = self.CalibrationSettingsRequest(
                reserved0=_normalize_arg(args[0], c_ubyte*8),
                adc_mult=_normalize_arg(args[1], c_float),
                adcv_offset=_normalize_arg(args[2], c_float),
                current_sense1_mult=_normalize_arg(args[3], c_float),
                current_sense1_offset=_normalize_arg(args[4], c_float),
                current_sense2_mult=_normalize_arg(args[5], c_float),
                current_sense2_offset=_normalize_arg(args[6], c_float),
                current_sense3_mult=_normalize_arg(args[7], c_float),
                current_sense3_offset=_normalize_arg(args[8], c_float),
                reserved1=_normalize_arg(args[9], c_ubyte*72)
            )
        else:
            src_buffer = args[0]
        _validate_call(_lib.ivm_set_calibration_settings(self._handle, byref(src_buffer)))

    def __init__(self, uri, defer_open=False):
        if isinstance(uri, str):
            uri = uri.encode("utf-8")
        if not isinstance(uri, (bytes, bytearray)):
            raise ValueError()
        self._uri = uri
        self._handle = None
        if not defer_open:
            self.open()
    if version_info >= (3, 4):
        def __del__(self):
            if self._handle:
                self.close()
    @property
    def uri(self):
        return self._uri

    def open(self):
        if self._handle is not None:
            return False

        handle = _lib.ivm_open_device(self._uri)
        if handle.value == _DeviceUndefined:
            raise RuntimeError()

        self._handle = handle
        return True

    def lib_version(self):
        ver_lib = create_string_buffer(str.encode("00.00.00"))
        result = _lib.ivm_libversion(ver_lib)
        if result != _Ok:
            raise RuntimeError()
        version_lib = ver_lib.value.decode("utf-8")
        return version_lib

    def close(self):
        if self._handle is None:
            return False

        try:
            result = _lib.ivm_close_device(byref(self._handle))
            if result != _Ok:
                raise RuntimeError()
        except:
            raise
        else:
            return True
        finally:
            self._handle = None

    def get_profile(self):
        buffer = c_char_p()
        @CFUNCTYPE(c_void_p, c_size_t)
        def allocate(size):
            # http://bugs.python.org/issue1574593
            return cast(create_string_buffer(size+1), c_void_p).value
        _validate_call(_lib.ivm_get_profile(self._handle, byref(buffer), allocate))
        return buffer.value.decode("utf-8")

    def set_profile(self, source):
        if isinstance(source, str):
            source = source.encode("utf-8")
        _validate_call(_lib.ivm_set_profile(self._handle, c_char_p(source), len(source)))
