13.3.1.6. Справочник по API¶
Публичный интерфейс пакета openmv состоит из класса Camera для взаимодействия с камерой и иерархии OMVException для ошибок протокола. Оба описаны на этой странице.
13.3.1.6.1. Класс Camera¶
- class openmv.Camera(port: str, *, baudrate: int = 921600, crc: bool = True, seq: bool = True, ack: bool = True, events: bool = True, timeout: float = 1.0, max_retry: int = 3, max_payload: int = 4096, drop_rate: float = 0.0)¶
Прокси на стороне хоста для камеры OpenMV, доступной через USB serial.
- Параметры:
port – Путь к последовательному устройству. В Linux это
/dev/ttyACMxдля USB CDC и/dev/ttyUSBxдля моста USB-to-UART. В macOS это/dev/tty.usbmodem...или/dev/cu.usbmodem.... В Windows этоCOMx.baudrate – Скорость передачи (бод) последовательного порта. По USB значение
921600является магическим значением, которое переключает камеру из MicroPython REPL в протокол OpenMV – любое другое значение по USB-соединению оставляет камеру в режиме REPL, поэтому необходимо использовать значение по умолчанию. По UART-соединению это фактическая скорость передачи (бод) линии, и её можно свободно задавать на обеих сторонах.crc – Включить проверку CRC для каждого пакета.
seq – Включить порядковые номера для каждого пакета.
ack – Требовать подтверждение пакетов.
events – Включить уведомления о событиях от камеры.
timeout – Тайм-аут на операцию в секундах.
max_retry – Число повторных попыток до возбуждения исключения при сбое пакета.
max_payload – Максимальный согласованный размер полезной нагрузки в байтах. Камера может согласовать меньшее значение.
drop_rate – Вероятность сброса пакета (только для тестов) в диапазоне
[0.0, 1.0]. В продакшене оставляйте0.0.
Класс поддерживает протокол менеджера контекста;
with Camera(port) as cam:вызываетconnect()при входе иdisconnect()при выходе.
13.3.1.6.2. Подключение¶
- Camera.connect() None¶
Открыть последовательный порт и выполнить рукопожатие протокола. В качестве побочного эффекта заполняется кэшированное состояние (список каналов, информация о системе, информация о версии). Вызывается автоматически менеджером контекста.
- Camera.disconnect() None¶
Закрыть последовательный порт и освободить транспорт. Вызывается автоматически при выходе из менеджера контекста.
- Camera.boot() None¶
Перевести камеру в её загрузчик. Соединение разрывается, так как камера перезагружается.
- Camera.update_capabilities() None¶
Повторно согласовать возможности протокола (CRC, проверка последовательности, ACK, события, максимальная полезная нагрузка) с камерой. Камера сообщает максимальную полезную нагрузку, которую она может обработать; запрос хоста ограничивается этим значением, а согласованные настройки отправляются обратно. Вызывается автоматически из
connect()– нет причин вызывать этот метод из пользовательского кода, кроме случаев, когда флаги конструктора нужно повторно согласовать на уже установленном соединении.
13.3.1.6.3. Выполнение скриптов¶
13.3.1.6.4. Потоковая передача¶
- Camera.streaming(enable: bool, raw: bool = False, resolution: tuple[int, int] | None = None) None¶
Включить или выключить поток кадров и выбрать формат передачи по проводу.
- Параметры:
enable –
Trueвключает потоковую передачу,Falseотключает её.raw – При значении
False(по умолчанию) камера сжимает каждый кадр в JPEG перед помещением его в канал потока, аread_frame()распаковывает его на хосте. При значенииTrueкамера отправляет захваченный буфер пикселей без сжатия – правильный выбор для камер без аппаратной поддержки JPEG, где программное сжатие является самым медленным шагом в цикле.resolution –
(width, height)– целевой размер, до которого камера масштабирует каждый сырой кадр перед отправкой, поскольку несжатые кадры намного больше сжатых в JPEG. Обязательно приraw=True; в противном случае игнорируется.
- Camera.read_frame() dict | None¶
Прочитать последний кадр из канала потока.
- Результат:
None, если кадр не ожидается, или словарь с ключамиwidth(int, пиксели),height(int, пиксели),format(int, идентификатор формата пикселей, объявленный камерой),depth(int, размер сжатого изображения в байтах для кадров JPEG / PNG; не используется для несжатых форматов),data(bytes, RGB888 длинойwidth * height * 3) иraw_size(int, байты, отправленные камерой по USB до декодирования).
13.3.1.6.5. Пользовательские каналы¶
- Camera.has_channel(name: str) bool¶
- Результат:
True, если на камере существует канал, зарегистрированный с именемname.
- Camera.channel_size(name: str) int¶
- Результат:
Число байтов, доступных в данный момент в названном канале, или
0, когда канал пуст или не существует.
- Camera.channel_read(name: str, size: int | None = None) bytes | None¶
Прочитать из пользовательского канала.
- Camera.channel_write(name: str, data: bytes) bool¶
Записать
dataв пользовательский канал. Записи больше полезной нагрузки автоматически разбиваются на пакеты.- Параметры:
name – Имя канала, зарегистрированное скриптом на стороне камеры.
data – Полезная нагрузка типа bytes-like для отправки.
- Результат:
True, если канал существует и запись была отправлена,Falseв противном случае.
- Camera.read_status() dict[str, bool]¶
Опросить каждый зарегистрированный канал.
- Результат:
Словарь, сопоставляющий имя канала логическому значению «данные готовы к чтению».
- Camera.update_channels() None¶
Обновить кэшированный список каналов из камеры. Запускается автоматически при следующем поиске канала по имени после поступления события регистрации канала; приложение, желающее немедленно узнать о только что зарегистрированном канале, может вызвать этот метод напрямую.
- Camera.get_channel(name: str | None = None, channel_id: int | None = None) int | str | None¶
Найти канал либо по имени (возвращая его числовой ID), либо по ID (возвращая его имя). Сначала обновляет кэш каналов через
update_channels(), если есть ожидающие события регистрации каналов.- Параметры:
name – Имя канала для разрешения в ID.
channel_id – ID канала для разрешения в имя.
- Результат:
Соответствующий ID или имя, или
None, когда канал не существует. Должен быть указан один из аргументовnameилиchannel_id.
13.3.1.6.6. Интроспекция устройства¶
- Camera.version() dict¶
Вернуть тройки версий протокола, загрузчика и прошивки камеры. Кэшируются после
connect(). Каждая тройка является кортежем(major, minor, patch)изint:protocol_version– версия проводного протокола OpenMV, реализуемого камерой.bootloader_version– образ загрузчика, находящийся во флеш-памяти.firmware_version– прошивка MicroPython, выполняющаяся в данный момент.
- Camera.system_info() dict¶
Вернуть информацию об аппаратных возможностях и памяти камеры. Кэшируется после
connect(). Ключи возвращаемого словаря делятся на четыре группы.Идентификация
cpu_id– 32-битный идентификатор CPU.device_id– кортеж из 3 32-битных слов, уникальный серийный номер устройства, зашитый в кремний.chip_id– кортеж из 3 32-битных слов, по одной записи на каждый датчик изображения, подключённый к камере.usb_vid– USB vendor ID.usb_pid– USB product ID.
Размеры памяти (все в килобайтах)
flash_size_kb– общий объём внутренней флеш-памяти.ram_size_kb– общий объём RAM.framebuffer_size_kb– RAM, зарезервированная для захвата изображений.stream_buffer_size_kb– RAM, зарезервированная для канала потока, который передаёт кадры на хост.
Флаги возможностей (по одному логическому значению на функцию, все названы
<feature>_present)gpu_present– графический процессор.npu_present– нейронный процессор.isp_present– процессор обработки сигнала изображения.venc_present– видеокодировщик.jpeg_present– аппаратный JPEG-кодировщик.dram_present– внешняя DRAM.crc_present– ускоритель CRC.pmu_present– блок мониторинга производительности.wifi_present– радиомодуль Wi-Fi.bt_present– радиомодуль Bluetooth.sd_present– слот для SD-карты.eth_present– Ethernet PHY.multicore_present– несколько ядер CPU.
Прочее
usb_highspeed– логическое значение,True, когда USB перечислился в высокоскоростном режиме (USB 2.0 HS, 480 Мбит/с).pmu_eventcnt– число доступных счётчиков событий PMU;0, когда PMU отсутствует.
13.3.1.6.7. Диагностика¶
13.3.1.6.8. Профайлер¶
Профайлер сообщает количество вызовов каждой функции, а также минимальное / максимальное / суммарное время выполнения для инструментированных модулей прошивки – в настоящее время image, ml и ulab. Вход и выход из функций перехватываются на этапе компиляции; во время выполнения берётся отсчёт монотонного микросекундного счётчика на каждом из них, результат накапливается по функциям, и таблица предоставляется хосту через канал profile.
Профайлер встраивается в прошивку только тогда, когда make передаётся PROFILE_ENABLE=1. Стандартные образы прошивки не включают его – флаг -finstrument-functions, который сборка добавляет к отслеживаемым модулям, имеет нетривиальные накладные расходы во время выполнения, поэтому сборки с профилированием создаются из исходного кода для конкретной отладочной сессии, которой они нужны. Когда прошивка собрана без этого флага, канал profile не регистрируется, и каждый метод профайлера на этой странице молча возвращает управление, ничего не делая.
Performance Monitoring Unit (PMU) от Arm – это блок аппаратных счётчиков Cortex-M55: небольшой набор настраиваемых счётчиков, которые отслеживают количество тактов, попадания и промахи кэша, поведение ветвлений и другие определённые архитектурой события, не замедляя измеряемый код. На камерах, у которых он есть – AE3 и N6, две камеры в линейке OpenMV, построенные на M55 – профайлер снимает показания этих счётчиков вместе с данными о времени, и суммы событий отображаются в каждой записи по функции. Камеры без PMU всё равно создают записи о времени; поля событий возвращаются нулевыми, а profiler_event() не выполняет никаких действий.
- Camera.profiler_mode(exclusive: bool = False) None¶
Переключаться между инклюзивным и эксклюзивным измерением времени. Инклюзивное измерение относит время вызываемых функций на счёт вызывающей; эксклюзивное измерение этого не делает.
- Параметры:
exclusive –
Trueвыбирает эксклюзивное измерение времени,Falseвыбирает инклюзивное.
- Camera.profiler_reset(config: list | None = None) None¶
Очистить все счётчики профиля.
config=Noneтакже восстанавливает назначение событий PMU по умолчанию.- Параметры:
config – Зарезервировано для будущих переопределений конфигурации по каждому счётчику. Передайте
None, чтобы сохранить значения по умолчанию.
- Camera.profiler_event(counter_num: int, event_id: int) None¶
Привязать один из слотов счётчиков PMU к конкретному аппаратному событию.
- Параметры:
counter_num – Индекс счётчика.
event_id – Определённый архитектурой идентификатор события.
- Camera.read_profile() list[dict] | None¶
Вернуть записи профиля по каждой функции, собранные с момента последнего сброса. Каждая запись является словарём с ключами
address,caller,call_count,min_ticks,max_ticks,total_ticks,total_cyclesи кортежемeventsразмером, равнымpmu_eventcntкамеры.- Результат:
Список словарей записей или
None, если канал профиля недоступен или данные не были собраны.
13.3.1.6.9. Наследование и внутреннее устройство каналов¶
Описанные выше методы покрывают каждое распространённое применение пакета. Несколько шаблонов – обработка событий со стороны камеры, на которые хост хочет реагировать, блокировка канала для многошагового обмена, взаимодействие с каналами, передающими структурированные данные вместо потоков байтов, или управление специфичными для канала командами – требуют методов, которые Camera держит с префиксом подчёркивания. Эти имена являются приватными по соглашению (Python не выполняет для них name-mangling), и предполагается, что приложения, которым они нужны, либо наследуют Camera, либо вызывают эти методы напрямую.
Наследование для реакции на события. Каждое событие, которое испускает камера, поступает через Camera._handle_event(). Наследование Camera и переопределение этого метода – это способ, которым приложение реагирует на события, возбуждаемые его скриптом на стороне камеры; страница События подробно описывает полный шаблон.
- Camera._handle_event(channel_id: int, event: int) None¶
Диспетчеризовать одно событие от камеры. Вызывается транспортным уровнем всякий раз, когда поступает пакет события. Переопределите в подклассе для добавления специфичной для приложения обработки; вызовите
super()._handle_event(...), чтобы сохранить поведение по умолчанию (обновление списка каналов приCHANNEL_REGISTERED, отслеживание готовности кадра на каналеstream, логирование старта / остановки каналаstdin).- Параметры:
channel_id –
0для системных событий, иначе зарегистрированный ID канала.event – Идентификатор события; значения берутся из перечисления
EventTypeдля системных событий и из того, что выбрал бэкенд канала на стороне камеры для событий канала.
Подкласс, добавляющий собственные методы взаимодействия по протоколу, должен декорировать их с помощью retry_if_failed(), чтобы они наследовали то же поведение ресинхронизации и повторных попыток, которое есть у каждого поставляемого метода на этой странице.
- static Camera.retry_if_failed(func)¶
Декоратор. Оборачивает метод экземпляра так, чтобы он повторял попытку один раз, когда транспорт возбуждает
ResyncException. Любой метод, который вызывает_send_cmd_wait_resp()(напрямую или через одну из обёрток_channel_*), должен нести этот декоратор:class MyCamera(Camera): @Camera.retry_if_failed def my_custom_command(self, payload): return self._send_cmd_wait_resp(Opcode.MY_CMD, 0, payload)
Блокировка канала гарантирует, что состояние канала не изменится между двумя связанными операциями (например, _channel_size(), за которым следует _channel_read(), на канале, который продолжает добавлять данные). read_frame() и read_profile() используют это внутренне; приложение, управляющее пользовательским каналом с многошаговым доступом, делает то же самое.
- Camera._channel_lock(channel_id: int) bool¶
Получить эксклюзивную блокировку на канал. Другие операции хоста на том же канале блокируются до освобождения блокировки.
- Параметры:
channel_id – Числовой ID канала, обычно разрешаемый через
get_channel().- Результат:
True, когда блокировка была предоставлена.
- Camera._channel_unlock(channel_id: int) bool¶
Освободить блокировку, ранее полученную через
_channel_lock(). Всегда используется в паре с вызовом блокировки; используйтеtry/finally, чтобы гарантировать снятие блокировки, даже когда чтение между ними возбуждает исключение.- Параметры:
channel_id – Числовой ID канала, обычно разрешаемый через
get_channel().
Структурированные каналы передают структурированные записи, а не плоский поток байтов. Канал профайлера является поставляемым примером: его форма равна (record_count, record_size), и хост, желающий узнать, сколько записей ожидается, читает форму, а не размер в байтах.
- Camera._channel_shape(channel_id: int) tuple[int, ...]¶
Прочитать дескриптор формы канала.
- Параметры:
channel_id – Числовой ID канала, обычно разрешаемый через
get_channel().- Результат:
Кортеж беззнаковых 32-битных целых чисел, описывающий компоновку канала. Смысл зависит от конкретного канала.
Специфичные для канала команды управления – start, stop, reset, configure – передаются одним опкодом (CHANNEL_IOCTL) со специфичным для канала номером команды и необязательной полезной нагрузкой struct.pack. Поставляемые методы, такие как stop(), exec() и streaming(), являются тонкими обёртками вокруг вызовов _channel_ioctl() к каналам stdin и stream; пользовательский канал на стороне камеры, определяющий собственное меню ioctl, управляется тем же способом.
- Camera._channel_ioctl(channel_id: int, cmd: int, fmt: str | None = None, *args) bytes | None¶
Выдать команду ioctl на канале.
- Параметры:
channel_id – Числовой ID канала, обычно разрешаемый через
get_channel().cmd – Номер команды, определённый бэкендом канала на стороне камеры.
fmt – Необязательная строка формата
structдля кортежа аргументов. ПередайтеNoneдля ioctl, не принимающих аргументов.args – Значения, соответствующие
fmt.
- Результат:
Любая полезная нагрузка, возвращённая каналом, или
None.
Варианты потока байтов по ID публичных методов канала пропускают поиск имени по ID и принимают явное байтовое смещение offset – полезно для чтения фрагмента из середины большого буфера (например, записей канала profile).
- Camera._channel_size(channel_id: int) int¶
- Параметры:
channel_id – Числовой ID канала, обычно разрешаемый через
get_channel().- Результат:
Байты, доступные в данный момент на канале.
- Camera._channel_read(channel_id: int, offset: int, length: int) bytes¶
Прочитать
lengthбайтов, начиная со смещенияoffset. Многопакетные чтения собираются автоматически.- Параметры:
channel_id – Числовой ID канала, обычно разрешаемый через
get_channel().offset – Байтовое смещение, с которого начинать чтение.
length – Число байтов для чтения.
- Camera._channel_write(channel_id: int, data: bytes, offset: int = 0) None¶
Записать
dataпо заданному смещениюoffset. Многопакетные записи автоматически разбиваются на пакеты.- Параметры:
channel_id – Числовой ID канала, обычно разрешаемый через
get_channel().data – Полезная нагрузка типа bytes-like для записи.
offset – Байтовое смещение, с которого начинать запись.
Примитивы протокола – это самый низкий уровень, который предоставляет класс: записи сырой отправки команды, получения сырого списка каналов и ручной ресинхронизации, на которых в конечном счёте построено всё вышеперечисленное. Приложение обращается к ним при отправке опкода, который класс ещё не оборачивает, или при реализации пользовательского восстановления в подклассе.
- Camera._send_cmd_wait_resp(opcode: int, channel: int = 0, data: bytes = b'') bytes | None¶
Отправить команду протокола и дождаться ответа камеры. Примитив, на котором построен каждый другой метод в этом разделе.
- Параметры:
opcode – Номер команды. Поставляемое перечисление
Opcodeперечисляет коды, с которыми поставляется прошивка, но параметр является просто целым числом – пользовательская сборка прошивки может определять и отвечать на собственные.channel – ID канала или
0для системных команд.data – Специфичная для команды полезная нагрузка.
- Результат:
Полезная нагрузка ответа или
Noneдля команд вродеOpcode.SYS_RESETиOpcode.SYS_BOOT, которые разрывают соединение.
- Camera._channel_list() dict¶
Получить текущий список каналов от камеры, не затрагивая кэшированные словари
channels_by_idиchannels_by_name, которые заполняетupdate_channels(). Полезно для подкласса, желающего напрямую проверить состояние каналов камеры.- Результат:
Словарь, сопоставляющий ID канала с
{'name': str, 'flags': int}.
- Camera._resync() None¶
Повторно выполнить рукопожатие протокола с нуля. Вызывается автоматически из
connect()при начальном подключении и каждым публичным методом, который перехватываетOMVExceptionот транспорта. Приложение, реализующее собственный цикл восстановления в подклассе, может вызвать этот метод напрямую после обработки исходной ошибки.
13.3.1.6.10. Исключения¶
- exception openmv.OMVException¶
Базовый класс для каждой ошибки уровня протокола. Все три подкласса ниже наследуют от него, поэтому единственный
except OMVExceptionпокрывает всю поверхность ошибок.
- exception openmv.TimeoutException¶
Камера не ответила в течение настроенного тайм-аута. Подкласс
OMVException.
- exception openmv.ChecksumException¶
CRC пакета не совпал. Возбуждается после того, как протокол исчерпал бюджет повторных попыток. Подкласс
OMVException.
- exception openmv.SequenceException¶
Пакет прибыл с неожиданным порядковым номером после повторных попыток. Подкласс
OMVException.