13.3.1.6. Referência da API

A interface pública do pacote openmv é a classe Camera para comunicar com uma câmara e a hierarquia OMVException para erros de protocolo. Ambas estão documentadas nesta página.

13.3.1.6.1. A classe 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)

O proxy do lado do anfitrião para uma câmara OpenMV acessível via série USB.

Parâmetros:
  • port – Caminho do dispositivo série. Em Linux, /dev/ttyACMx para USB CDC e /dev/ttyUSBx para uma ponte USB-para-UART. Em macOS, /dev/tty.usbmodem... ou /dev/cu.usbmodem.... Em Windows, COMx.

  • baudrate – Taxa de baud série. Sobre USB, 921600 é o valor mágico que faz a câmara transitar do REPL MicroPython para o protocolo OpenMV – qualquer outro valor numa ligação USB mantém a câmara em modo REPL, pelo que o valor predefinido deve ser utilizado. Sobre uma ligação UART, o valor é a taxa de baud real da linha e pode ser definido livremente em ambos os lados.

  • crc – Activar a validação CRC em cada pacote.

  • seq – Activar números de sequência por pacote.

  • ack – Exigir confirmação de recepção de pacotes.

  • events – Activar notificações de eventos da câmara.

  • timeout – Tempo limite por operação, em segundos.

  • max_retry – Número de tentativas antes de lançar uma excepção num pacote com falha.

  • max_payload – Tamanho máximo negociado do payload em bytes. A câmara pode negociar um valor inferior.

  • drop_rate – Probabilidade de descarte de um pacote, apenas para testes, em [0.0, 1.0]. Deixar em 0.0 em produção.

A classe suporta o protocolo de gestor de contexto; with Camera(port) as cam: invoca connect() na entrada e disconnect() na saída.

13.3.1.6.2. Ligação

Camera.connect() None

Abre a porta série e efectua o handshake do protocolo. O estado em cache (lista de canais, informação do sistema, informação de versão) é populado como efeito secundário. Invocado automaticamente pelo gestor de contexto.

Camera.disconnect() None

Fecha a porta série e liberta o transporte. Invocado automaticamente quando o gestor de contexto termina.

Camera.is_connected() bool
Retorno:

True se a porta série estiver aberta.

Camera.reset() None

Reinicia a câmara. A ligação é interrompida porque a câmara reinicia.

Camera.boot() None

Coloca a câmara no seu bootloader. A ligação é interrompida porque a câmara reinicia.

Camera.update_capabilities() None

Renegocia as capacidades do protocolo (CRC, verificação de sequência, ACKs, eventos, payload máximo) com a câmara. A câmara comunica o payload máximo que consegue gerir; o pedido do anfitrião é limitado a esse valor e as definições acordadas são enviadas de volta. Invocado automaticamente por connect() – não há razão para o invocar a partir de código do utilizador, a não ser que os parâmetros do construtor precisem de ser renegociados numa ligação existente.

Camera.poll_events() None

Executa uma vez o caminho de recepção do transporte para consumir quaisquer eventos pendentes da câmara sem enviar um comando. Útil em programas de longa duração que ficam vários minutos sem outra E/S e que pretendem apresentar eventos de registo de canal de forma atempada.

13.3.1.6.3. Execução de scripts

Camera.exec(script: str) None

Carrega script (uma cadeia de caracteres de fonte Python) no buffer stdin da câmara e inicia a sua execução.

Parâmetros:

script – Código fonte MicroPython a executar.

Camera.stop() None

Interrompe o script em execução. Equivalente ao botão Stop do IDE.

Camera.read_stdout() str | None

Lê todos os bytes que o script em execução escreveu em stdout desde a última chamada.

Retorno:

A saída como cadeia de caracteres descodificada, ou None se não houver dados em espera.

13.3.1.6.4. Streaming

Camera.streaming(enable: bool, raw: bool = False, resolution: tuple[int, int] | None = None) None

Liga ou desliga o stream de fotogramas e selecciona o formato de transmissão.

Parâmetros:
  • enableTrue activa o streaming, False desactiva-o.

  • raw – Quando False (predefinição), a câmara comprime cada fotograma em JPEG antes de o colocar no canal de stream e read_frame() descomprime no anfitrião. Quando True, a câmara envia o buffer de pixels capturado sem compressão – a escolha correcta em câmaras sem suporte de hardware JPEG, onde a compressão por software é o passo mais lento no ciclo.

  • resolution(width, height) alvo para o qual a câmara reduz cada fotograma bruto antes de o enviar, uma vez que os fotogramas não comprimidos são muito maiores do que os comprimidos em JPEG. Obrigatório quando raw=True; ignorado caso contrário.

Camera.read_frame() dict | None

Lê o fotograma mais recente do canal de stream.

Retorno:

None se não houver fotograma em espera, ou um dict com as chaves width (int, pixels), height (int, pixels), format (int, o identificador de formato de pixel declarado pela câmara), depth (int, o tamanho da imagem comprimida em bytes para fotogramas JPEG / PNG; não utilizado para formatos não comprimidos), data (bytes, RGB888 de comprimento width * height * 3), e raw_size (int, bytes enviados pela câmara via USB antes da descodificação).

13.3.1.6.5. Canais personalizados

Camera.has_channel(name: str) bool
Retorno:

True se existir um canal registado com name na câmara.

Camera.channel_size(name: str) int
Retorno:

Número de bytes que o canal com o nome indicado tem actualmente disponíveis, ou 0 quando o canal está vazio ou não existe.

Camera.channel_read(name: str, size: int | None = None) bytes | None

Lê de um canal personalizado.

Parâmetros:
  • name – Nome do canal registado pelo script do lado da câmara.

  • size – Bytes a ler, ou None para ler o que estiver disponível.

Retorno:

Os bytes, ou None se o canal não existir.

Camera.channel_write(name: str, data: bytes) bool

Escreve data num canal personalizado. Escritas maiores que o payload são automaticamente divididas entre pacotes.

Parâmetros:
  • name – Nome do canal registado pelo script do lado da câmara.

  • data – Payload do tipo bytes a enviar.

Retorno:

True se o canal existir e a escrita tiver sido enviada, False caso contrário.

Camera.read_status() dict[str, bool]

Sonda todos os canais registados.

Retorno:

Dict que mapeia o nome do canal para um booleano indicando se «há dados prontos a ler».

Camera.update_channels() None

Actualiza a lista de canais em cache a partir da câmara. É executado automaticamente da próxima vez que uma pesquisa de canal por nome for efectuada após a chegada de um evento de registo de canal; uma aplicação que queira conhecer imediatamente um canal recém-registado pode invocar este método directamente.

Camera.get_channel(name: str | None = None, channel_id: int | None = None) int | str | None

Procura um canal pelo nome (devolvendo o seu ID numérico) ou pelo ID (devolvendo o seu nome). Actualiza a cache de canais via update_channels() primeiro, se houver eventos de registo de canal pendentes.

Parâmetros:
  • name – Nome do canal a resolver para um ID.

  • channel_id – ID do canal a resolver para um nome.

Retorno:

O ID ou nome correspondente, ou None quando o canal não existe. Um de name ou channel_id deve ser fornecido.

13.3.1.6.6. Introspecção do dispositivo

Camera.version() dict

Devolve os triplos de versão do protocolo, do bootloader e do firmware da câmara. Em cache após connect(). Cada triplo é um tuplo (major, minor, patch) de int:

  • protocol_version – a versão do protocolo de rede OpenMV que a câmara implementa.

  • bootloader_version – a imagem do bootloader residente em flash.

  • firmware_version – o firmware MicroPython actualmente em execução.

Camera.system_info() dict

Devolve as informações de capacidade de hardware e memória da câmara. Em cache após connect(). As chaves do dict devolvido estão agrupadas em quatro grupos.

Identidade

  • cpu_id – identificador de CPU de 32 bits.

  • device_id – 3-tuplo de palavras de 32 bits, o número de série único do dispositivo integrado no silício.

  • chip_id – 3-tuplo de palavras de 32 bits, uma entrada por sensor de imagem ligado à câmara.

  • usb_vid – ID de fornecedor USB.

  • usb_pid – ID de produto USB.

Tamanhos de memória (todos em kilobytes)

  • flash_size_kb – flash interna total.

  • ram_size_kb – RAM total.

  • framebuffer_size_kb – RAM reservada para a captura de imagem.

  • stream_buffer_size_kb – RAM reservada para o canal de stream que envia fotogramas para o anfitrião.

Indicadores de capacidade (um booleano por característica, todos com o nome <feature>_present)

  • gpu_present – unidade de processamento gráfico.

  • npu_present – unidade de processamento neuronal.

  • isp_present – processador de sinal de imagem.

  • venc_present – codificador de vídeo.

  • jpeg_present – codificador de hardware JPEG.

  • dram_present – DRAM externa.

  • crc_present – acelerador de CRC.

  • pmu_present – unidade de monitorização de desempenho.

  • wifi_present – rádio Wi-Fi.

  • bt_present – rádio Bluetooth.

  • sd_present – ranhura para cartão SD.

  • eth_present – PHY Ethernet.

  • multicore_present – múltiplos núcleos de CPU.

Outros

  • usb_highspeed – booleano, True quando o USB é enumerado em modo de alta velocidade (USB 2.0 HS, 480 Mbps).

  • pmu_eventcnt – número de contadores de eventos PMU disponíveis; 0 quando não há PMU.

Camera.print_system_info() None

Regista o bloco de informações do sistema formatado em logging ao nível INFO. O CLI utiliza isto na ligação.

13.3.1.6.7. Diagnósticos

Camera.host_stats() dict
Retorno:

Os contadores da camada de transporte rastreados no lado do anfitrião: sent, received, checksum, sequence.

Camera.device_stats() dict
Retorno:

Os contadores da camada de transporte rastreados no lado da câmara: sent, received, checksum, sequence, retransmit, transport, sent_events, max_ack_queue_depth.

13.3.1.6.8. Profiler

O profiler reporta contagens de chamadas por função e tempos de execução mínimos / máximos / totais para os módulos de firmware instrumentados – actualmente image, ml e ulab. A entrada e saída de funções são interceptadas em tempo de compilação; o runtime recolhe amostras de um contador de microssegundos monotónico em cada intercepção, acumula o resultado por função e expõe a tabela ao anfitrião através do canal profile.

O profiler só é integrado no firmware quando PROFILE_ENABLE=1 é passado ao make. As imagens de firmware stock não o incluem – o indicador -finstrument-functions que a compilação adiciona aos módulos rastreados tem uma sobrecarga de runtime não negligenciável, pelo que as compilações de profiling são produzidas a partir do código fonte para a sessão de depuração específica que delas necessita. Quando o firmware não foi compilado com o indicador, o canal profile não fica registado e todos os métodos do profiler nesta página retornam silenciosamente sem fazer nada.

A Performance Monitoring Unit (PMU) da Arm é o bloco de contadores de hardware do Cortex-M55 – um pequeno conjunto de contadores configuráveis que rastreiam contagens de ciclos, acertos e erros de cache, comportamento de ramificações e outros eventos definidos pela arquitectura sem abrandar o código sob medição. Nas câmaras que a possuem – a AE3 e a N6, as duas câmaras da gama OpenMV construídas em torno do M55 – o profiler recolhe amostras destes contadores juntamente com os dados de temporização e os totais de eventos surgem em cada registo por função. As câmaras sem PMU continuam a produzir registos de temporização; os campos de eventos retornam como zero e profiler_event() é uma operação sem efeito.

Camera.profiler_mode(exclusive: bool = False) None

Alterna entre temporização inclusiva e exclusiva. A temporização inclusiva imputa o tempo dos chamados ao chamador; a temporização exclusiva não o faz.

Parâmetros:

exclusiveTrue selecciona a temporização exclusiva, False selecciona a inclusiva.

Camera.profiler_reset(config: list | None = None) None

Limpa todos os contadores de perfil. config=None também repõe a atribuição predefinida de eventos PMU.

Parâmetros:

config – Reservado para futuras substituições de configuração por contador. Passe None para manter os valores predefinidos.

Camera.profiler_event(counter_num: int, event_id: int) None

Associa uma das ranhuras de contador PMU a um evento de hardware específico.

Parâmetros:
  • counter_num – Índice do contador.

  • event_id – Identificador de evento definido pela arquitectura.

Camera.read_profile() list[dict] | None

Devolve os registos de perfil por função recolhidos desde o último reset. Cada registo é um dict com address, caller, call_count, min_ticks, max_ticks, total_ticks, total_cycles e um tuplo events dimensionado ao pmu_eventcnt da câmara.

Retorno:

Lista de dicts de registos, ou None se o canal de perfil não estiver disponível ou não tiverem sido recolhidos dados.

13.3.1.6.9. Subclassificação e internos de canais

Os métodos documentados acima cobrem todos os usos comuns do pacote. Alguns padrões – tratar eventos do lado da câmara aos quais o anfitrião quer reagir, bloquear um canal para uma troca em múltiplos passos, comunicar com canais que transportam dados estruturados em vez de streams de bytes, ou executar comandos de controlo específicos de canal – necessitam de métodos que Camera mantém prefixados com um sublinhado. Estes nomes são privados por convenção (Python não os manipula com name-mangling), e as aplicações que deles necessitam devem subclassificar Camera ou invocar os métodos directamente.

Subclassificação para reagir a eventos. Cada evento emitido pela câmara chega através de Camera._handle_event(). Subclassificar Camera e substituir o método é a forma de uma aplicação reagir aos eventos que o seu script do lado da câmara lança; a página Eventos percorre o padrão completo.

Camera._handle_event(channel_id: int, event: int) None

Processa um evento proveniente da câmara. Invocado pela camada de transporte sempre que chega um pacote de evento. Substituir numa subclasse para adicionar tratamento específico da aplicação; invocar super()._handle_event(...) para manter o comportamento predefinido (actualização da lista de canais em CHANNEL_REGISTERED, rastreamento de fotogramas prontos no canal stream, registo de início / paragem do canal stdin).

Parâmetros:
  • channel_id0 para eventos do sistema, caso contrário o ID do canal registado.

  • event – Identificador do evento; os valores provêm do enum EventType para eventos do sistema e do que o backend do canal do lado da câmara escolheu para eventos de canal.

Uma subclasse que adiciona os seus próprios métodos de comunicação de protocolo deve decorá-los com retry_if_failed() para que herdem o mesmo comportamento de ressincronização e nova tentativa que todos os métodos disponibilizados nesta página possuem.

static Camera.retry_if_failed(func)

Decorador. Envolve um método de instância de modo a que este tente novamente uma vez quando o transporte lança ResyncException. Qualquer método que invoque _send_cmd_wait_resp() (directamente ou através de um dos wrappers _channel_*) deve ter este decorador:

class MyCamera(Camera):
    @Camera.retry_if_failed
    def my_custom_command(self, payload):
        return self._send_cmd_wait_resp(Opcode.MY_CMD,
                                        0, payload)

O bloqueio de canal garante que o estado do canal não muda entre duas operações relacionadas (um _channel_size() seguido de um _channel_read(), por exemplo, num canal que continua a acrescentar dados). read_frame() e read_profile() utilizam isto internamente; uma aplicação que controla um canal personalizado com acesso em múltiplos passos faz o mesmo.

Camera._channel_lock(channel_id: int) bool

Adquire um bloqueio exclusivo num canal. Outras operações do anfitrião no mesmo canal ficam bloqueadas até o bloqueio ser libertado.

Parâmetros:

channel_id – ID numérico do canal, normalmente resolvido com get_channel().

Retorno:

True quando o bloqueio foi concedido.

Camera._channel_unlock(channel_id: int) bool

Liberta um bloqueio anteriormente adquirido com _channel_lock(). Sempre emparelhado com uma chamada de bloqueio; use try / finally para garantir que o desbloqueio acontece mesmo quando a leitura intermédia lança uma excepção.

Parâmetros:

channel_id – ID numérico do canal, normalmente resolvido com get_channel().

Os canais estruturados transportam registos estruturados em vez de um stream de bytes simples. O canal do profiler é o exemplo disponibilizado: a sua forma é (record_count, record_size) e um anfitrião que quer saber quantos registos estão em espera lê a forma em vez do tamanho em bytes.

Camera._channel_shape(channel_id: int) tuple[int, ...]

Lê o descritor de forma de um canal.

Parâmetros:

channel_id – ID numérico do canal, normalmente resolvido com get_channel().

Retorno:

Tuplo de inteiros de 32 bits sem sinal que descreve a disposição do canal. O significado é específico de cada canal.

Comandos de controlo específicos de canal – iniciar, parar, reiniciar, configurar – utilizam um único opcode (CHANNEL_IOCTL) com um número de comando específico do canal e um payload opcional struct.pack. Os métodos disponibilizados como stop(), exec() e streaming() são wrappers simples em torno de chamadas _channel_ioctl() nos canais stdin e stream; um canal personalizado do lado da câmara que define o seu próprio menu ioctl é controlado da mesma forma.

Camera._channel_ioctl(channel_id: int, cmd: int, fmt: str | None = None, *args) bytes | None

Emite um comando ioctl num canal.

Parâmetros:
  • channel_id – ID numérico do canal, normalmente resolvido com get_channel().

  • cmd – Número de comando definido pelo backend do canal do lado da câmara.

  • fmt – Cadeia de formato struct opcional para o tuplo de argumentos. Passe None para ioctls que não recebem argumentos.

  • args – Valores correspondentes a fmt.

Retorno:

O payload devolvido pelo canal, ou None.

Variantes de stream de bytes por ID dos métodos públicos de canal ignoram a pesquisa nome-para-ID e aceitam um offset de bytes explícito – útil para ler um bloco do meio de um buffer grande (os registos do canal profile, por exemplo).

Camera._channel_size(channel_id: int) int
Parâmetros:

channel_id – ID numérico do canal, normalmente resolvido com get_channel().

Retorno:

Bytes actualmente disponíveis no canal.

Camera._channel_read(channel_id: int, offset: int, length: int) bytes

length bytes a partir de offset. As leituras de múltiplos pacotes são remontadas automaticamente.

Parâmetros:
  • channel_id – ID numérico do canal, normalmente resolvido com get_channel().

  • offset – Offset de bytes a partir do qual iniciar a leitura.

  • length – Número de bytes a ler.

Camera._channel_write(channel_id: int, data: bytes, offset: int = 0) None

Escreve data no offset indicado. As escritas de múltiplos pacotes são divididas entre pacotes automaticamente.

Parâmetros:
  • channel_id – ID numérico do canal, normalmente resolvido com get_channel().

  • data – Payload do tipo bytes a escrever.

  • offset – Offset de bytes a partir do qual iniciar a escrita.

Os primitivos de protocolo são o nível mais baixo que a classe expõe – as entradas brutas de envio de comando, obtenção da lista de canais bruta e ressincronização manual sobre as quais tudo o acima está eventualmente construído. Uma aplicação recorre a eles quando envia um opcode que a classe ainda não encapsula, ou quando implementa recuperação personalizada numa subclasse.

Camera._send_cmd_wait_resp(opcode: int, channel: int = 0, data: bytes = b'') bytes | None

Envia um comando de protocolo e aguarda a resposta da câmara. O primitivo sobre o qual todos os outros métodos desta secção estão construídos.

Parâmetros:
  • opcode – Número do comando. O enum Opcode disponibilizado lista os códigos com os quais o firmware é fornecido, mas o parâmetro é apenas um inteiro – uma compilação de firmware personalizada pode definir e responder aos seus próprios.

  • channel – ID do canal, ou 0 para comandos do sistema.

  • data – Payload específico do comando.

Retorno:

Payload da resposta, ou None para comandos como Opcode.SYS_RESET e Opcode.SYS_BOOT que interrompem a ligação.

Camera._channel_list() dict

Obtém a lista de canais actual da câmara sem tocar nos dicionários channels_by_id e channels_by_name em cache que update_channels() popula. Útil para uma subclasse que quer inspeccionar o estado de canais da câmara directamente.

Retorno:

Dict que mapeia o ID do canal para {'name': str, 'flags': int}.

Camera._resync() None

Volta a executar o handshake do protocolo do início. Invocado automaticamente por connect() na ligação inicial e por todos os métodos públicos que apanham uma OMVException do transporte. Uma aplicação que implementa o seu próprio ciclo de recuperação numa subclasse pode invocar este método directamente após tratar o erro subjacente.

13.3.1.6.10. Excepções

exception openmv.OMVException

Classe base para todos os erros ao nível do protocolo. As três subclasses abaixo herdam todas dela, pelo que um único except OMVException cobre toda a superfície de erros.

exception openmv.TimeoutException

A câmara não respondeu dentro do tempo limite configurado. Subclasse de OMVException.

exception openmv.ChecksumException

O CRC de um pacote não correspondeu. Lançada após o protocolo ter esgotado o seu orçamento de novas tentativas. Subclasse de OMVException.

exception openmv.SequenceException

Um pacote chegou com um número de sequência inesperado após as novas tentativas. Subclasse de OMVException.