13.3.1.6. Référence de l’API

La surface publique du paquet openmv se compose de la classe Camera pour communiquer avec une cam et de la hiérarchie OMVException pour les erreurs de protocole. Les deux sont documentées sur cette page.

13.3.1.6.1. La 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)

Le proxy côté hôte d’une cam OpenMV accessible via le port série USB.

Paramètres:
  • port – Chemin du périphérique série. Sous Linux, /dev/ttyACMx pour l’USB CDC et /dev/ttyUSBx pour un pont USB-vers-UART. Sous macOS, /dev/tty.usbmodem... ou /dev/cu.usbmodem.... Sous Windows, COMx.

  • baudrate – Débit en bauds du port série. Via USB, 921600 est la valeur magique qui fait passer la cam du REPL MicroPython au protocole OpenMV – toute autre valeur sur une liaison USB laisse la cam en mode REPL, il faut donc utiliser la valeur par défaut. Via une liaison UART, la valeur correspond au débit réel de la ligne et peut être définie librement des deux côtés.

  • crc – Active la validation CRC sur chaque paquet.

  • seq – Active les numéros de séquence par paquet.

  • ack – Exige l’accusé de réception des paquets.

  • events – Active les notifications d’événements depuis la cam.

  • timeout – Délai d’expiration par opération, en secondes.

  • max_retry – Nombre de tentatives avant de lever une exception sur un paquet en échec.

  • max_payload – Taille maximale de charge utile négociée, en octets. La cam peut négocier une valeur inférieure.

  • drop_rate – Probabilité, à des fins de test uniquement, d’abandonner un paquet, dans [0.0, 1.0]. Laissez à 0.0 en production.

La classe prend en charge le protocole de gestionnaire de contexte ; with Camera(port) as cam: appelle connect() à l’entrée et disconnect() à la sortie.

13.3.1.6.2. Connexion

Camera.connect() None

Ouvre le port série et effectue la poignée de main du protocole. L’état mis en cache (liste des canaux, informations système, informations de version) est renseigné comme effet de bord. Appelée automatiquement par le gestionnaire de contexte.

Camera.disconnect() None

Ferme le port série et libère le transport. Appelée automatiquement à la sortie du gestionnaire de contexte.

Camera.is_connected() bool
Renvoie:

True si le port série est ouvert.

Camera.reset() None

Réinitialise la cam. La connexion est interrompue car la cam redémarre.

Camera.boot() None

Fait passer la cam dans son bootloader. La connexion est interrompue car la cam redémarre.

Camera.update_capabilities() None

Renégocie les capacités du protocole (CRC, vérification de séquence, ACK, événements, charge utile maximale) avec la cam. La cam indique la charge utile maximale qu’elle peut gérer ; la requête de l’hôte est limitée à cette valeur et les réglages convenus sont renvoyés. Appelée automatiquement par connect() – il n’y a aucune raison de l’appeler depuis le code utilisateur, sauf si les indicateurs du constructeur doivent être renégociés sur une connexion existante.

Camera.poll_events() None

Exécute une fois le chemin de réception du transport pour consommer tous les événements en attente de la cam sans envoyer de commande. Utile dans les programmes de longue durée qui restent plusieurs minutes sans autre E/S et qui souhaitent faire remonter rapidement les événements d’enregistrement de canal.

13.3.1.6.3. Exécution de script

Camera.exec(script: str) None

Téléverse script (une chaîne de code source Python) dans le tampon stdin de la cam et démarre son exécution.

Paramètres:

script – Code source MicroPython à exécuter.

Camera.stop() None

Interrompt le script en cours d’exécution. Équivalent au bouton Stop de l’IDE.

Camera.read_stdout() str | None

Lit les octets que le script en cours d’exécution a écrits sur stdout depuis le dernier appel.

Renvoie:

La sortie sous forme de chaîne décodée, ou None si aucune donnée n’est en attente.

13.3.1.6.4. Diffusion en continu

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

Active ou désactive le flux de trames et choisit le format sur le fil.

Paramètres:
  • enableTrue active la diffusion, False la désactive.

  • raw – Lorsque False (par défaut), la cam compresse chaque trame en JPEG avant de la placer dans le canal de flux, et read_frame() la décompresse côté hôte. Lorsque True, la cam envoie le tampon de pixels capturé sans compression – le bon choix sur les cams dépourvues de prise en charge matérielle du JPEG, où la compression logicielle constitue l’étape la plus lente de la boucle.

  • resolution – Cible (width, height) vers laquelle la cam réduit chaque trame brute avant l’envoi, puisque les trames non compressées sont bien plus volumineuses que celles compressées en JPEG. Obligatoire lorsque raw=True ; ignoré sinon.

Camera.read_frame() dict | None

Lit la dernière trame du canal de flux.

Renvoie:

None si aucune trame n’est en attente, ou un dictionnaire avec les clés width (int, pixels), height (int, pixels), format (int, l’identifiant de format de pixel déclaré par la cam), depth (int, la taille de l’image compressée en octets pour les trames JPEG / PNG ; inutilisé pour les formats non compressés), data (bytes, RGB888 de longueur width * height * 3) et raw_size (int, octets envoyés par la cam via USB avant le décodage).

13.3.1.6.5. Canaux personnalisés

Camera.has_channel(name: str) bool
Renvoie:

True s’il existe sur la cam un canal enregistré sous le nom name.

Camera.channel_size(name: str) int
Renvoie:

Nombre d’octets actuellement disponibles sur le canal nommé, ou 0 lorsque le canal est vide ou n’existe pas.

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

Lit depuis un canal personnalisé.

Paramètres:
  • name – Nom du canal enregistré par le script côté cam.

  • size – Octets à lire, ou None pour lire tout ce qui est disponible.

Renvoie:

Les octets, ou None si le canal n’existe pas.

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

Écrit data dans un canal personnalisé. Les écritures dépassant la charge utile sont automatiquement réparties sur plusieurs paquets.

Paramètres:
  • name – Nom du canal enregistré par le script côté cam.

  • data – Charge utile de type octets à envoyer.

Renvoie:

True si le canal existe et que l’écriture a été envoyée, False sinon.

Camera.read_status() dict[str, bool]

Interroge chaque canal enregistré.

Renvoie:

Dictionnaire associant le nom du canal à un booléen indiquant « des données sont prêtes à être lues ».

Camera.update_channels() None

Actualise la liste des canaux mise en cache depuis la cam. S’exécute automatiquement lors de la prochaine recherche de canal par nom après l’arrivée d’un événement d’enregistrement de canal ; une application souhaitant connaître immédiatement un canal nouvellement enregistré peut appeler cette méthode directement.

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

Recherche un canal soit par nom (renvoyant son ID numérique), soit par ID (renvoyant son nom). Actualise d’abord le cache des canaux via update_channels() si des événements d’enregistrement de canal sont en attente.

Paramètres:
  • name – Nom du canal à résoudre en ID.

  • channel_id – ID du canal à résoudre en nom.

Renvoie:

L’ID ou le nom correspondant, ou None lorsque le canal n’existe pas. L’un des deux, name ou channel_id, doit être fourni.

13.3.1.6.6. Introspection du périphérique

Camera.version() dict

Retourne les triplets de version de protocole, de bootloader et de micrologiciel de la cam. Mis en cache après connect(). Chaque triplet est un tuple (major, minor, patch) de int :

  • protocol_version – la version du protocole filaire OpenMV que la cam implémente.

  • bootloader_version – l’image du bootloader résidente en mémoire flash.

  • firmware_version – le micrologiciel MicroPython actuellement en cours d’exécution.

Camera.system_info() dict

Retourne les informations sur les capacités matérielles et la mémoire de la cam. Mises en cache après connect(). Les clés du dictionnaire retourné se répartissent en quatre groupes.

Identité

  • cpu_id – identifiant CPU 32 bits.

  • device_id – tuple de 3 mots de 32 bits, le numéro de série unique du périphérique gravé dans le silicium.

  • chip_id – tuple de 3 mots de 32 bits, une entrée par capteur d’image connecté à la cam.

  • usb_vid – ID fournisseur USB.

  • usb_pid – ID produit USB.

Tailles de mémoire (toutes en kilooctets)

  • flash_size_kb – mémoire flash interne totale.

  • ram_size_kb – RAM totale.

  • framebuffer_size_kb – RAM réservée à la capture d’image.

  • stream_buffer_size_kb – RAM réservée au canal de flux qui transmet les trames à l’hôte.

Indicateurs de capacité (un booléen par fonctionnalité, tous nommés <feature>_present)

  • gpu_present – unité de traitement graphique.

  • npu_present – unité de traitement neuronal.

  • isp_present – processeur de signal d’image.

  • venc_present – encodeur vidéo.

  • jpeg_present – encodeur matériel JPEG.

  • dram_present – DRAM externe.

  • crc_present – accélérateur CRC.

  • pmu_present – unité de surveillance des performances.

  • wifi_present – radio Wi-Fi.

  • bt_present – radio Bluetooth.

  • sd_present – emplacement pour carte SD.

  • eth_present – PHY Ethernet.

  • multicore_present – plusieurs cœurs CPU.

Autres

  • usb_highspeed – booléen, True lorsque l’USB est énuméré en mode haute vitesse (USB 2.0 HS, 480 Mbit/s).

  • pmu_eventcnt – nombre de compteurs d’événements PMU disponibles ; 0 en l’absence de PMU.

Camera.print_system_info() None

Consigne le bloc d’informations système formaté dans logging au niveau INFO. La CLI l’utilise lors de la connexion.

13.3.1.6.7. Diagnostics

Camera.host_stats() dict
Renvoie:

Les compteurs de la couche transport suivis côté hôte : sent, received, checksum, sequence.

Camera.device_stats() dict
Renvoie:

Les compteurs de la couche transport suivis côté cam : sent, received, checksum, sequence, retransmit, transport, sent_events, max_ack_queue_depth.

13.3.1.6.8. Profileur

Le profileur rapporte le nombre d’appels par fonction ainsi que les temps d’exécution min / max / total pour les modules de micrologiciel instrumentés – actuellement image, ml et ulab. L’entrée et la sortie des fonctions sont interceptées à la compilation ; l’exécution échantillonne un compteur monotone en microsecondes à chacune, accumule le résultat par fonction et expose la table à l’hôte via le canal profile.

Le profileur n’est intégré au micrologiciel que lorsque PROFILE_ENABLE=1 est passé à make. Les images de micrologiciel standard ne l’incluent pas – l’indicateur -finstrument-functions que la compilation ajoute aux modules suivis induit une surcharge d’exécution non négligeable, c’est pourquoi les versions de profilage sont produites à partir des sources pour la session de débogage spécifique qui en a besoin. Lorsque le micrologiciel n’a pas été compilé avec cet indicateur, le canal profile n’est pas enregistré et chaque méthode de profilage de cette page retourne silencieusement sans rien faire.

L”unité de surveillance des performances (PMU) Arm est le bloc de compteurs matériels du Cortex-M55 – un petit ensemble de compteurs configurables qui suivent les comptages de cycles, les succès et échecs de cache, le comportement des branchements et d’autres événements définis par l’architecture, sans ralentir le code mesuré. Sur les cams qui en disposent – l’AE3 et la N6, les deux cams de la gamme OpenMV construites autour du M55 – le profileur échantillonne ces compteurs en parallèle des données de temps, et les totaux d’événements apparaissent dans chaque enregistrement par fonction. Les cams sans PMU produisent tout de même des enregistrements de temps ; les champs d’événements reviennent à zéro et profiler_event() est sans effet.

Camera.profiler_mode(exclusive: bool = False) None

Bascule entre le chronométrage inclusif et exclusif. Le chronométrage inclusif impute le temps des appelés à l’appelant ; le chronométrage exclusif ne le fait pas.

Paramètres:

exclusiveTrue sélectionne le chronométrage exclusif, False sélectionne l’inclusif.

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

Réinitialise tous les compteurs de profilage. config=None restaure également l’affectation par défaut des événements PMU.

Paramètres:

config – Réservé pour de futures surcharges de configuration par compteur. Passez None pour conserver les valeurs par défaut.

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

Associe l’un des emplacements de compteur PMU à un événement matériel spécifique.

Paramètres:
  • counter_num – Index du compteur.

  • event_id – Identifiant d’événement défini par l’architecture.

Camera.read_profile() list[dict] | None

Retourne les enregistrements de profilage par fonction collectés depuis la dernière réinitialisation. Chaque enregistrement est un dictionnaire avec address, caller, call_count, min_ticks, max_ticks, total_ticks, total_cycles et un tuple events dimensionné selon le pmu_eventcnt de la cam.

Renvoie:

Liste de dictionnaires d’enregistrements, ou None si le canal de profilage n’est pas disponible ou si aucune donnée n’a été collectée.

13.3.1.6.9. Sous-classement et internes des canaux

Les méthodes documentées ci-dessus couvrent tous les usages courants du paquet. Quelques motifs – gérer les événements côté cam auxquels l’hôte souhaite réagir, verrouiller un canal pour un échange en plusieurs étapes, communiquer avec des canaux qui transportent des données structurées plutôt que des flux d’octets, ou piloter des commandes de contrôle propres à un canal – nécessitent des méthodes que Camera conserve préfixées d’un trait de soulignement. Ces noms sont privés par convention (Python ne les soumet pas au name-mangling), et les applications qui en ont besoin sont censées soit sous-classer Camera, soit appeler les méthodes directement.

Sous-classement pour réagir aux événements. Chaque événement émis par la cam arrive via Camera._handle_event(). Sous-classer Camera et surcharger la méthode est la façon dont une application réagit aux événements levés par son script côté cam ; la page Événements détaille le motif complet.

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

Distribue un événement de la cam. Appelée par la couche transport chaque fois qu’un paquet d’événement arrive. Surchargez-la dans une sous-classe pour ajouter un traitement propre à l’application ; appelez super()._handle_event(...) pour conserver le comportement par défaut (actualisation de la liste des canaux sur CHANNEL_REGISTERED, suivi de la disponibilité des trames sur le canal stream, journalisation du démarrage / arrêt du canal stdin).

Paramètres:
  • channel_id0 pour les événements système, sinon l’ID du canal enregistré.

  • event – Identifiant d’événement ; les valeurs proviennent de l’énumération EventType pour les événements système et de ce que le backend de canal côté cam a choisi pour les événements de canal.

Une sous-classe qui ajoute ses propres méthodes de communication avec le protocole doit les décorer avec retry_if_failed() afin qu’elles héritent du même comportement de resynchronisation et de nouvelle tentative que chaque méthode livrée sur cette page.

static Camera.retry_if_failed(func)

Décorateur. Enveloppe une méthode d’instance afin qu’elle réessaie une fois lorsque le transport lève ResyncException. Toute méthode qui appelle _send_cmd_wait_resp() (directement ou via l’un des wrappers _channel_*) doit porter ce décorateur

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

Le verrouillage de canal garantit que l’état du canal ne change pas entre deux opérations liées (un _channel_size() suivi d’un _channel_read(), par exemple, sur un canal qui continue d’ajouter des données). read_frame() et read_profile() l’utilisent en interne ; une application pilotant un canal personnalisé avec un accès en plusieurs étapes fait de même.

Camera._channel_lock(channel_id: int) bool

Acquiert un verrou exclusif sur un canal. Les autres opérations de l’hôte sur le même canal se bloquent jusqu’à ce que le verrou soit libéré.

Paramètres:

channel_id – ID numérique du canal, généralement résolu avec get_channel().

Renvoie:

True lorsque le verrou a été accordé.

Camera._channel_unlock(channel_id: int) bool

Libère un verrou précédemment pris avec _channel_lock(). Toujours associé à un appel de verrouillage ; utilisez try / finally pour garantir que le déverrouillage a lieu même lorsque la lecture intermédiaire lève une exception.

Paramètres:

channel_id – ID numérique du canal, généralement résolu avec get_channel().

Les canaux structurés transportent des enregistrements structurés plutôt qu’un flux d’octets plat. Le canal du profileur en est l’exemple livré : sa forme est (record_count, record_size) et un hôte qui veut savoir combien d’enregistrements sont en attente lit la forme plutôt que la taille en octets.

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

Lit le descripteur de forme d’un canal.

Paramètres:

channel_id – ID numérique du canal, généralement résolu avec get_channel().

Renvoie:

Tuple d’entiers non signés 32 bits décrivant la disposition du canal. La signification dépend du canal.

Les commandes de contrôle propres à un canal – démarrer, arrêter, réinitialiser, configurer – utilisent un unique opcode (CHANNEL_IOCTL) avec un numéro de commande propre au canal et une charge utile struct.pack facultative. Les méthodes livrées comme stop(), exec() et streaming() sont de minces wrappers autour d’appels _channel_ioctl() sur les canaux stdin et stream ; un canal personnalisé côté cam qui définit son propre menu d’ioctl se pilote de la même façon.

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

Émet une commande ioctl sur un canal.

Paramètres:
  • channel_id – ID numérique du canal, généralement résolu avec get_channel().

  • cmd – Numéro de commande défini par le backend de canal côté cam.

  • fmt – Chaîne de format struct facultative pour le tuple d’arguments. Passez None pour les ioctls qui ne prennent aucun argument.

  • args – Valeurs correspondant à fmt.

Renvoie:

La charge utile retournée par le canal, ou None.

Les variantes de flux d’octets par ID des méthodes de canal publiques évitent la recherche nom-vers-ID et acceptent un offset d’octet explicite – utile pour lire un fragment au milieu d’un grand tampon (les enregistrements du canal profile, par exemple).

Camera._channel_size(channel_id: int) int
Paramètres:

channel_id – ID numérique du canal, généralement résolu avec get_channel().

Renvoie:

Octets actuellement disponibles sur le canal.

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

Lit length octets à partir de offset. Les lectures multi-paquets sont réassemblées automatiquement.

Paramètres:
  • channel_id – ID numérique du canal, généralement résolu avec get_channel().

  • offset – Décalage en octets à partir duquel commencer la lecture.

  • length – Nombre d’octets à lire.

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

Écrit data au offset donné. Les écritures multi-paquets sont réparties automatiquement sur plusieurs paquets.

Paramètres:
  • channel_id – ID numérique du canal, généralement résolu avec get_channel().

  • data – Charge utile de type octets à écrire.

  • offset – Décalage en octets à partir duquel commencer l’écriture.

Les primitives de protocole constituent le niveau le plus bas que la classe expose – les entrées brutes d’envoi de commande, de récupération de la liste brute des canaux et de resynchronisation manuelle sur lesquelles tout ce qui précède finit par s’appuyer. Une application y a recours lors de l’envoi d’un opcode que la classe n’enveloppe pas déjà, ou lors de l’implémentation d’une récupération personnalisée dans une sous-classe.

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

Envoie une commande de protocole et attend la réponse de la cam. La primitive sur laquelle est construite toute autre méthode de cette section.

Paramètres:
  • opcode – Numéro de commande. L’énumération Opcode livrée liste les codes fournis avec le micrologiciel, mais le paramètre n’est qu’un entier – une version personnalisée du micrologiciel peut définir les siens et y répondre.

  • channel – ID du canal, ou 0 pour les commandes système.

  • data – Charge utile propre à la commande.

Renvoie:

Charge utile de réponse, ou None pour les commandes comme Opcode.SYS_RESET et Opcode.SYS_BOOT qui interrompent la connexion.

Camera._channel_list() dict

Récupère la liste actuelle des canaux depuis la cam sans toucher aux dictionnaires en cache channels_by_id et channels_by_name que update_channels() renseigne. Utile pour une sous-classe qui souhaite inspecter directement l’état des canaux de la cam.

Renvoie:

Dictionnaire associant l’ID du canal à {'name': str, 'flags': int}.

Camera._resync() None

Réexécute la poignée de main du protocole depuis zéro. Appelée automatiquement par connect() lors de la connexion initiale et par chaque méthode publique qui intercepte une OMVException du transport. Une application implémentant sa propre boucle de récupération dans une sous-classe peut l’appeler directement après avoir géré l’erreur sous-jacente.

13.3.1.6.10. Exceptions

exception openmv.OMVException

Classe de base de toute erreur au niveau du protocole. Les trois sous-classes ci-dessous en héritent toutes, de sorte qu’un unique except OMVException couvre l’ensemble de la surface d’erreur.

exception openmv.TimeoutException

La cam n’a pas répondu dans le délai d’expiration configuré. Sous-classe de OMVException.

exception openmv.ChecksumException

Le CRC d’un paquet ne correspondait pas. Levée après que le protocole a épuisé son budget de tentatives. Sous-classe de OMVException.

exception openmv.SequenceException

Un paquet est arrivé avec un numéro de séquence inattendu après les tentatives. Sous-classe de OMVException.