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 التسلسلي.
- المعاملات:
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، التحقق من التسلسل، الإقرارات، الأحداث، الحد الأقصى للحمولة) مع الكاميرا. تبلّغ الكاميرا عن الحد الأقصى للحمولة التي يمكنها التعامل معها؛ ويُقتطَع طلب المضيف إلى تلك القيمة وتُعاد الإعدادات المتفق عليها. يُستدعى تلقائياً بواسطة
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_write(name: str, data: bytes) bool¶
كتابة
dataإلى قناة مخصّصة. تُقسَّم عمليات الكتابة الأكبر من الحمولة تلقائياً عبر حزم متعددة.- المعاملات:
name -- اسم القناة المسجّل بواسطة البرنامج النصي من جانب الكاميرا.
data -- الحمولة المراد إرسالها من النوع الشبيه بالبايتات.
- القيمة المُعادة:
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¶
البحث عن قناة إما بالاسم (مع إعادة معرّفها الرقمي) أو بالمعرّف (مع إعادة اسمها). يُحدّث ذاكرة القنوات المؤقتة عبر
update_channels()أولاً إذا كانت أحداث تسجيل القنوات معلّقة.- المعاملات:
name -- اسم القناة المراد ترجمته إلى معرّف.
channel_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 بت.device_id-- صفّ ثلاثي من كلمات بطول 32 بت، وهو الرقم التسلسلي الفريد للجهاز المطبوع في السيليكون.chip_id-- صفّ ثلاثي من كلمات بطول 32 بت، إدخال واحد لكل مستشعر صورة متصل بالكاميرا.usb_vid-- معرّف مُصنّع USB.usb_pid-- معرّف منتج USB.
أحجام الذاكرة (جميعها بالكيلوبايت)
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-- نوى متعددة لوحدة المعالجة المركزية.
أخرى
usb_highspeed-- قيمة منطقية، تكونTrueعندما يُعدّ USB في وضع السرعة العالية (USB 2.0 HS، بسرعة 480 ميجابت/ث).pmu_eventcnt-- عدد عدّادات أحداث PMU المتاحة؛0عند عدم وجود PMU.
13.3.1.6.7. التشخيصات¶
13.3.1.6.8. أداة التحليل (Profiler)¶
تُبلّغ أداة التحليل عن عدد استدعاءات كل دالة وأزمنة التنفيذ الدنيا / القصوى / الإجمالية لوحدات البرنامج الثابت المُجهَّزة بالقياس -- وهي حالياً image و ml و ulab. تُعترَض نقطة دخول الدالة والخروج منها وقت الترجمة؛ ويأخذ زمن التشغيل عيّنة من عدّاد ميكروثانية رتيب عند كل منهما، ويجمّع النتيجة لكل دالة، ويعرض الجدول للمضيف عبر قناة profile.
تُبنى أداة التحليل في البرنامج الثابت فقط عندما يُمرَّر PROFILE_ENABLE=1 إلى make. لا تتضمنها صور البرنامج الثابت القياسية -- فراية -finstrument-functions التي يضيفها البناء إلى الوحدات المتتبَّعة لها عبء تشغيلي غير ضئيل، لذا تُنتَج أبنية التحليل من المصدر لجلسة التنقيح المحددة التي تحتاج إليها. عندما لا يُبنى البرنامج الثابت بهذه الراية، لا تُسجَّل قناة profile وتعود كل دالة من دوال أداة التحليل في هذه الصفحة بصمت دون القيام بأي شيء.
تُعد وحدة مراقبة الأداء (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 أسماءها)، ويُتوقّع من التطبيقات التي تحتاجها إما إنشاء صنف فرعي من Camera أو استدعاء الدوال مباشرة.
إنشاء صنف فرعي للاستجابة للأحداث. يصل كل حدث تُطلقه الكاميرا عبر Camera._handle_event(). إن إنشاء صنف فرعي من Camera وتجاوز هذه الدالة هو الطريقة التي يستجيب بها تطبيق للأحداث التي يطلقها برنامجه النصي من جانب الكاميرا؛ وتشرح صفحة الأحداث النمط الكامل.
- Camera._handle_event(channel_id: int, event: int) None¶
توزيع حدث واحد من الكاميرا. يُستدعى بواسطة طبقة النقل كلما وصلت حزمة حدث. تجاوزه في صنف فرعي لإضافة معالجة خاصة بالتطبيق؛ استدعِ
super()._handle_event(...)للإبقاء على السلوك الافتراضي (تحديث قائمة القنوات عندCHANNEL_REGISTERED، وتتبّع جاهزية الإطار على قناةstream، وتسجيل بدء / إيقاف قناةstdin).- المعاملات:
channel_id --
0للأحداث على مستوى النظام، وإلا فمعرّف القناة المسجّلة.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 -- معرّف القناة الرقمي، يُحَل عادة بواسطة
get_channel().- القيمة المُعادة:
Trueعند منح القفل.
- Camera._channel_unlock(channel_id: int) bool¶
تحرير قفل أُخذ سابقاً بواسطة
_channel_lock(). يُقرَن دائماً باستدعاء قفل؛ استخدمtry/finallyللتأكد من حدوث فك القفل حتى عندما تطلق القراءة بينهما استثناءً.- المعاملات:
channel_id -- معرّف القناة الرقمي، يُحَل عادة بواسطة
get_channel().
القنوات ذات الشكل تحمل سجلات منظّمة بدلاً من تدفق بايتات مسطّح. قناة أداة التحليل هي المثال المُسلَّم: شكلها هو (record_count, record_size) ويقرأ المضيف الذي يريد معرفة عدد السجلات المنتظرة الشكلَ بدلاً من حجم البايتات.
- Camera._channel_shape(channel_id: int) tuple[int, ...]¶
قراءة واصف شكل قناة.
- المعاملات:
channel_id -- معرّف القناة الرقمي، يُحَل عادة بواسطة
get_channel().- القيمة المُعادة:
صفّ من الأعداد الصحيحة غير المُوقَّعة بطول 32 بت تصف تخطيط القناة. المعنى خاص بكل قناة.
أوامر التحكم الخاصة بالقناة -- البدء، الإيقاف، إعادة التعيين، التهيئة -- تركب رمز عملية واحد (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 -- معرّف القناة الرقمي، يُحَل عادة بواسطة
get_channel().cmd -- رقم الأمر المعرّف بواسطة الواجهة الخلفية للقناة من جانب الكاميرا.
fmt -- سلسلة تنسيق
structاختيارية لصفّ الوسائط. مرّرNoneلأوامر ioctl التي لا تأخذ وسائط.args -- قيم مطابقة لـ
fmt.
- القيمة المُعادة:
أي حمولة أعادتها القناة، أو
None.
متغيرات تدفق البايتات حسب المعرّف من دوال القناة العامة تتخطى البحث من الاسم إلى المعرّف وتقبل إزاحة بايت offset صريحة -- مفيدة لقراءة جزء من وسط مخزن مؤقت كبير (سجلات قناة profile، على سبيل المثال).
- Camera._channel_size(channel_id: int) int¶
- المعاملات:
channel_id -- معرّف القناة الرقمي، يُحَل عادة بواسطة
get_channel().- القيمة المُعادة:
البايتات المتاحة حالياً على القناة.
- Camera._channel_read(channel_id: int, offset: int, length: int) bytes¶
قراءة
lengthبايت بدءاً منoffset. تُعاد تجميع القراءات متعددة الحزم تلقائياً.- المعاملات:
channel_id -- معرّف القناة الرقمي، يُحَل عادة بواسطة
get_channel().offset -- إزاحة البايت التي تبدأ القراءة منها.
length -- عدد البايتات المراد قراءتها.
- Camera._channel_write(channel_id: int, data: bytes, offset: int = 0) None¶
كتابة
dataعندoffsetالمعطى. تُقسَّم عمليات الكتابة متعددة الحزم عبر حزم متعددة تلقائياً.- المعاملات:
channel_id -- معرّف القناة الرقمي، يُحَل عادة بواسطة
get_channel().data -- الحمولة المراد كتابتها من النوع الشبيه بالبايتات.
offset -- إزاحة البايت التي تبدأ الكتابة عندها.
أوّليّات البروتوكول هي أدنى مستوى يكشفه الصنف -- وهي إدخالات الإرسال الخام للأمر، وجلب قائمة القنوات الخام، وإعادة المزامنة اليدوية التي يُبنى عليها كل ما سبق في نهاية المطاف. يلجأ إليها التطبيق عند إرسال رمز عملية لا يغلّفه الصنف بالفعل، أو عند تنفيذ استرداد مخصّص في صنف فرعي.
- Camera._send_cmd_wait_resp(opcode: int, channel: int = 0, data: bytes = b'') bytes | None¶
إرسال أمر بروتوكول وانتظار استجابة الكاميرا. الأوّليّة التي تُبنى عليها كل دالة أخرى في هذا القسم.
- المعاملات:
opcode -- رقم الأمر. يسرد تعداد
Opcodeالمُسلَّم الرموز التي يأتي بها البرنامج الثابت، لكن المعامل ليس سوى عدد صحيح -- يمكن لبناء برنامج ثابت مخصّص أن يعرّف رموزه الخاصة ويستجيب لها.channel -- معرّف القناة، أو
0لأوامر النظام.data -- حمولة خاصة بالأمر.
- القيمة المُعادة:
حمولة الاستجابة، أو
Noneللأوامر مثلOpcode.SYS_RESETوOpcode.SYS_BOOTالتي تُسقط الاتصال.
- Camera._channel_list() dict¶
جلب قائمة القنوات الحالية من الكاميرا دون المساس بقاموسي
channels_by_idوchannels_by_nameالمخزّنين مؤقتاً اللذين تملؤهماupdate_channels(). مفيد لصنف فرعي يريد فحص حالة قنوات الكاميرا مباشرة.- القيمة المُعادة:
قاموس يربط معرّف القناة بـ
{'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.