lora --- مشغّل مودم LoRa

توفّر الوحدة lora مشغّلاً لمودم LoRa من نوع Murata CMWX1ZZABZ الموجود على Arduino Portenta Vision Shield. وهي تتيح فئة عالية المستوى Lora تغلّف مجموعة أوامر AT المستخدمة من قبل البرنامج الثابت للمودم (بما في ذلك البرنامج الثابت Arduino MKRWAN ARD-078) بحيث يستطيع التطبيق الانضمام إلى شبكة LoRaWAN وإرسال/استقبال الحزم.

مثال:

import lora

modem = lora.Lora(band=lora.BAND_EU868, debug=True)
print("Device EUI:", modem.get_device_eui())
if modem.join_OTAA("0000000000000000", "00000000000000000000000000000000"):
    modem.send_data(b"hello", confirmed=True)

الثوابت

أوضاع التفعيل

lora.MODE_ABP: int

وضع التفعيل بالتخصيص (Activation By Personalization).

lora.MODE_OTAA: int

وضع التفعيل عبر الأثير (Over-The-Air Activation).

أوضاع خرج التردد الراديوي

lora.RF_MODE_RFO: int

استخدام خرج التردد الراديوي RFO (منخفض الطاقة) الخاص بالمودم.

lora.RF_MODE_PABOOST: int

استخدام خرج التردد الراديوي PA_BOOST (عالي الطاقة) الخاص بالمودم.

النطاقات

lora.BAND_AS923: int

النطاق الإقليمي AS923 (آسيا 923 ميجاهرتز).

lora.BAND_AU915: int

النطاق الإقليمي AU915 (أستراليا 915 ميجاهرتز).

lora.BAND_EU868: int

النطاق الإقليمي EU868 (أوروبا 868 ميجاهرتز).

lora.BAND_KR920: int

النطاق الإقليمي KR920 (كوريا 920 ميجاهرتز).

lora.BAND_IN865: int

النطاق الإقليمي IN865 (الهند 865 ميجاهرتز).

lora.BAND_US915: int

النطاق الإقليمي US915 (الولايات المتحدة 915 ميجاهرتز).

lora.BAND_US915_HYBRID: int

الخطة الإقليمية الهجينة US915 (نطاق فرعي).

فئات الأجهزة

lora.CLASS_A: str

جهاز LoRaWAN الطرفي من الفئة A.

lora.CLASS_B: str

جهاز LoRaWAN الطرفي من الفئة B.

lora.CLASS_C: str

جهاز LoRaWAN الطرفي من الفئة C.

الاستثناءات

exception lora.LoraError

الاستثناء الأساسي الذي يُطلَق لأي خطأ يُرجِعه المودم أو المشغّل.

exception lora.LoraErrorTimeout

يُطلَق عندما لا يستجيب المودم خلال المهلة المُهيَّأة (مخزن الاستقبال فارغ).

exception lora.LoraErrorParam

يُطلَق عند استجابة +ERR_PARAM حين يُصدَر أمر AT بمعامل غير صالح.

exception lora.LoraErrorBusy

يُطلَق عند استجابة +ERR_BUSY حين يكون المودم مشغولاً بمعالجة أمر سابق.

exception lora.LoraErrorOverflow

يُطلَق عند استجابة +ERR_PARAM_OVERFLOW حين يتجاوز معامل الطول الأقصى المسموح به.

exception lora.LoraErrorNoNetwork

يُطلَق عند استجابة +ERR_NO_NETWORK حين لا يكون المودم قد انضم إلى شبكة.

exception lora.LoraErrorRX

يُطلَق عند استجابة +ERR_RX حين يحدث خطأ أثناء استقبال وصلة نازلة.

exception lora.LoraErrorUnknown

يُطلَق عند استجابة +ERR_UNKNOWN أو حين يُبلِغ المودم عن خطأ غير موثّق.

الفئات

class lora.Lora(uart: machine.UART | None = None, rst_pin: machine.Pin | None = None, boot_pin: machine.Pin | None = None, band: int = BAND_EU868, poll_ms: int = 300000, debug: bool = False)

إنشاء مشغّل مودم جديد. يقوم المُنشئ بتهيئة (أو إنشاء تلقائي) دبابيس UART وإعادة الضبط/الإقلاع، ويُعيد ضبط الوحدة عتادياً، ويُجري مزامنة معدل الباود التلقائي (autobaud)، ويُعيد إقلاع الوحدة، ويستعلم عن إصدار برنامجها الثابت، ويُهيّئ النطاق الإقليمي band المطلوب.

المعاملات:
  • uart -- مثيل machine.UART مُهيَّأ مسبقاً يُستخدم للتواصل مع المودم. إذا كان None، يفتح المشغّل UART(8, 19200) بتأطير 8N2 (الإعداد الافتراضي لـ Portenta Vision Shield).

  • rst_pin -- مثيل machine.Pin يقود خط إعادة ضبط المودم. إذا كان None، يُهيّأ "PC6" كخرج دافع-ساحب (push-pull).

  • boot_pin -- مثيل machine.Pin يقود خط اختيار الإقلاع للمودم. إذا كان None، يُهيّأ "PG7" كخرج دافع-ساحب مسحوب إلى المستوى المنخفض.

  • band -- النطاق الإقليمي المراد تهيئته. أحد ثوابت BAND_*.

  • poll_ms -- الفاصل الزمني بالميلي ثانية بين الوصلات الصاعدة الفارغة التلقائية التي تطلقها poll() لإبقاء نافذة الوصلة النازلة مفتوحة.

  • debug -- عندما يكون True، تُطبَع كل حركة مرور UART عبر print().

LoraErrors: dict

التعيين من سلاسل استجابة الأخطاء للمودم (مثل "+ERR_BUSY") إلى فئة الاستثناء المقابلة. يُستخدم داخلياً من قبل handle_error().

init_modem() None

تهيئة كسولة لـ self.uart و self.rst_pin و self.boot_pin إلى إعداداتها الافتراضية لـ Portenta Vision Shield إن لم تكن مُعيَّنة مسبقاً. تُستدعى من المُنشئ؛ ولا يستدعيها كود المستخدم عادةً.

debug_print(data: str) None

تطبع data إذا كان debug مُفعَّلاً وقت الإنشاء، وإلا فلا تفعل شيئاً.

is_arduino_firmware() bool

تُرجِع True إذا كان المودم يشغّل البرنامج الثابت Arduino MKRWAN ARD-078 (يُكتشَف من سلسلة fw_version المخزّنة مؤقتاً).

configure_class(_class: str) None

تهيئة فئة جهاز LoRaWAN.

المعاملات:

_class -- أحد CLASS_A أو CLASS_B أو CLASS_C.

configure_band(band: int) bool

تهيئة النطاق الإقليمي، وعلى البرنامج الثابت Arduino مع BAND_EU868، تفعيل محدِّد دورة العمل وفق ETSI. تُرجِع True عند النجاح.

المعاملات:

band -- أحد ثوابت BAND_*.

set_baudrate(baudrate: int) None

تغيير معدل الباود لـ UART الخاص بالمودم (AT+UART).

المعاملات:

baudrate -- معدل الباود الجديد، بالبت في الثانية.

set_autobaud(timeout: int = 10000) bool

إرسال أوامر AT فارغة حتى يستجيب المودم بـ +OK أو حتى تنقضي timeout ميلي ثانية. تُرجِع True إذا نجحت المزامنة.

المعاملات:

timeout -- الحد الأقصى للوقت المراد قضاؤه في المحاولة، بالميلي ثانية.

get_fw_version() str

الاستعلام عن سلسلة جهاز المودم (AT+DEV?) وإصدار البرنامج الثابت (AT+VER?) وإرجاعهما كسلسلة واحدة مفصولة بمسافة.

get_device_eui() str

تُرجِع معرّف الجهاز Device EUI ذا الـ 64 بت للمودم كسلسلة سداسية عشرية.

factory_default() None

استعادة الإعدادات الافتراضية للمصنع عبر AT+FACNEW.

restart() None

إعادة مزامنة معدل الباود، وإعادة إقلاع المودم، وإعادة قراءة إصدار البرنامج الثابت، وإعادة تطبيق النطاق الإقليمي المُهيَّأ. يُطلِق LoraError عند الفشل.

set_rf_power(mode: int, power: int) None

تهيئة مرحلة خرج التردد الراديوي للمودم (AT+RFPOWER).

المعاملات:
  • mode -- أحد RF_MODE_RFO أو RF_MODE_PABOOST.

  • power -- مؤشر طاقة الخرج، بوحدات خاصة بالبرنامج الثابت.

set_port(port: int) None

تهيئة منفذ تطبيق LoRaWAN (1..223) المستخدَم في استدعاءات send_data() اللاحقة.

المعاملات:

port -- منفذ FPort لـ LoRaWAN.

set_public_network(enable: bool) None

تفعيل أو تعطيل كلمة المزامنة للشبكة العامة.

المعاملات:

enable -- True لكلمة مزامنة LoRaWAN العامة، و False للخاصة.

sleep(enable: bool) None

وضع المودم في سُبات منخفض الطاقة (True) أو إيقاظه (False).

format(hexMode: bool) None

اختيار تنسيق البيانات المستخدَم عبر UART لبايتات الحمولة.

المعاملات:

hexMode -- True لتنسيق الحمولة بالنظام السداسي العشري ASCII، و False للثنائي الخام.

set_datarate(dr: int) None

تعيين مؤشر معدل بيانات LoRaWAN (AT+DR).

المعاملات:

dr -- مؤشر معدل البيانات الخاص بالمنطقة.

get_datarate() int

تُرجِع مؤشر معدل بيانات LoRaWAN الحالي.

set_adr(adr: bool) None

تفعيل أو تعطيل معدل البيانات التكيفي (Adaptive Data Rate).

المعاملات:

adr -- True لتفعيل ADR، و False لتعطيله.

get_adr() int

تُرجِع إعداد ADR الحالي (1 إذا كان مُفعَّلاً، و 0 خلاف ذلك).

get_devaddr() str

تُرجِع عنوان الجهاز DevAddr الحالي ذا الـ 32 بت كسلسلة سداسية عشرية.

get_nwk_skey() str

تُرجِع مفتاح جلسة الشبكة الحالي كسلسلة سداسية عشرية.

get_appskey() str

تُرجِع مفتاح جلسة التطبيق الحالي كسلسلة سداسية عشرية.

get_rx2dr() int

تُرجِع مؤشر معدل البيانات المستخدَم لنافذة الاستقبال RX2.

set_rx2dr(dr: int) None

تعيين مؤشر معدل البيانات المستخدَم لنافذة الاستقبال RX2.

المعاملات:

dr -- مؤشر معدل البيانات الخاص بالمنطقة.

get_ex2freq() int

تُرجِع التردد، بالهرتز، المستخدَم لنافذة الاستقبال RX2.

set_rx2freq(freq: int) None

تعيين التردد المستخدَم لنافذة الاستقبال RX2.

المعاملات:

freq -- التردد بالهرتز.

set_fcu(fcu: int) None

تعيين عدّاد إطارات الوصلة الصاعدة (AT+FCU).

المعاملات:

fcu -- قيمة عدّاد إطارات الوصلة الصاعدة الجديدة.

get_fcu() int

تُرجِع عدّاد إطارات الوصلة الصاعدة الحالي.

set_fcd(fcd: int) None

تعيين عدّاد إطارات الوصلة النازلة (AT+FCD).

المعاملات:

fcd -- قيمة عدّاد إطارات الوصلة النازلة الجديدة.

get_fcd() int

تُرجِع عدّاد إطارات الوصلة النازلة الحالي.

change_mode(mode: int) None

تبديل وضع التفعيل.

المعاملات:

mode -- أحد MODE_ABP أو MODE_OTAA.

join(timeout_ms: int) bool

إصدار AT+JOIN والانتظار لحدث قبول الانضمام. تُرجِع True إذا أبلغ المودم عن +EVENT=1,1 (نجح الانضمام) خلال timeout_ms.

المعاملات:

timeout_ms -- الحد الأقصى للوقت المراد انتظاره لكل من +ACK وحدث الانضمام اللاحق، بالميلي ثانية.

get_join_status() bool

تُرجِع True إذا كان المودم منضماً حالياً إلى شبكة.

get_max_size() int

تُرجِع الحجم الأقصى لحمولة LoRaWAN، بالبايت، لمعدل البيانات الحالي. على البرنامج الثابت Arduino يكون هذا ثابتاً عند 64.

poll() None

إذا انقضى أكثر من poll_ms ميلي ثانية منذ آخر استدعاء، يُرسَل وصلة صاعدة مؤكَّدة فارغة لتفريغ الوصلات النازلة المعلّقة. مُخصَّص ليُستدعى بشكل متكرر من الحلقة الرئيسية للتطبيق.

send_data(buff: bytes, confirmed: bool = True) bool

إرسال وصلة صاعدة لـ LoRaWAN. يُطلِق LoraError إذا كان buff أكبر من get_max_size().

المعاملات:
  • buff -- بايتات الحمولة المراد إرسالها.

  • confirmed -- عندما يكون True، تُرسَل وصلة صاعدة مؤكَّدة (+CTX) ويُنتظَر +ACK من خادم الشبكة. وعندما يكون False، تُرسَل وصلة صاعدة غير مؤكَّدة (+UTX).

تُرجِع:

True إذا قبل المودم الحزمة (وفي حالة الوصلات الصاعدة المؤكَّدة، إذا أقرّتها الشبكة)، و False خلاف ذلك.

receive_data(timeout: int = 1000) dict | None

الانتظار لوصلة نازلة. تُرجِع None إذا لم يُستقبَل حدث +RECV خلال timeout ميلي ثانية، وإلا تُرجِع قاموساً {"port": str, "data": str} يحتوي على FPort وبايتات الحمولة.

المعاملات:

timeout -- الحد الأقصى للوقت المراد انتظاره، بالميلي ثانية.

receive(delimiter: str | list | None = None, max_bytes: int | None = None, timeout: int = 1000) str

قراءة UART منخفضة المستوى. تقرأ الأحرف من المودم حتى يُطابَق فاصل، أو حتى تُقرأ max_bytes حرفاً، أو حتى تنقضي timeout ميلي ثانية، ثم تُرجِع السلسلة المتراكمة مع إزالة أي \r لاحق.

المعاملات:
  • delimiter -- إما حرف واحد للمطابقة في نهاية المخزن، أو سلسلة متعددة الأحرف للمطابقة مقابل المخزن المُشذَّب الكامل، أو قائمة بمثل هذه السلاسل.

  • max_bytes -- إذا عُيِّن، تُرجِع بمجرد قراءة هذا العدد من البايتات بالضبط.

  • timeout -- المهلة الإجمالية للقراءة، بالميلي ثانية.

available() int

تُرجِع عدد البايتات المتاحة حالياً في مخزن استقبال UART الخاص بالمودم.

join_OTAA(appEui: str, appKey: str, devEui: str = None, timeout: int = 60000) bool

تبديل المودم إلى وضع OTAA، وبرمجة المفاتيح ومعرّفات EUI المقدّمة، ثم محاولة الانضمام إلى الشبكة. تُرجِع True إذا نجح الانضمام.

المعاملات:
  • appEui -- معرّف التطبيق/الانضمام Application/Join EUI ذو الـ 64 بت كسلسلة سداسية عشرية.

  • appKey -- مفتاح التطبيق Application Key ذو الـ 128 بت كسلسلة سداسية عشرية.

  • devEui -- معرّف الجهاز Device EUI الاختياري ذو الـ 64 بت كسلسلة سداسية عشرية. إذا كان None، يُستخدَم معرّف الجهاز المبرمَج من المصنع.

  • timeout -- مهلة الانضمام، بالميلي ثانية.

join_ABP(nwkId: int, devAddr: str, nwkSKey: str, appSKey: str, timeout: int = 60000) bool

تبديل المودم إلى وضع ABP، وبرمجة العناوين والمفاتيح المقدّمة، ثم محاولة الانضمام. تُرجِع نتيجة get_join_status().

المعاملات:
  • nwkId -- معرّف الشبكة (يتجاهله البرنامج الثابت حالياً).

  • devAddr -- عنوان الجهاز Device Address ذو الـ 32 بت كسلسلة سداسية عشرية.

  • nwkSKey -- مفتاح جلسة الشبكة Network Session Key ذو الـ 128 بت كسلسلة سداسية عشرية.

  • appSKey -- مفتاح جلسة التطبيق Application Session Key ذو الـ 128 بت كسلسلة سداسية عشرية.

  • timeout -- مهلة الانضمام، بالميلي ثانية.

handle_error(command: str, data: str) None

فحص استجابة المودم وإطلاق فئة LoraError الفرعية المطابِقة إذا كانت تمثّل خطأً. لا تفعل شيئاً للاستجابات غير الخاطئة.

المعاملات:
  • command -- أمر AT (بدون البادئة AT) الذي أنتج data.

  • data -- سلسلة الاستجابة التي أرجعها المودم.

send_command(cmd: str, *args, delimiter: str = '\\r', data: bytes = None, timeout: int = 1000, raise_error: bool = True) str

بناء أمر AT من cmd و args، وإلحاق حمولة data خام اختيارياً، وإرساله، وإرجاع استجابة المودم. لأوامر الاستعلام المنتهية بـ ?، يُرجَع جزء القيمة فقط (السلسلة الفرعية بعد =).

المعاملات:
  • cmd -- لاحقة أمر AT (مثل "+JOIN" و "+DR=")؛ تُضاف البادئة "AT" و \r اللاحق تلقائياً.

  • args -- وسائط إضافية تُسلسَل مع cmd بعد التحويل إلى سلسلة.

  • delimiter -- الفاصل المُمرَّر إلى receive().

  • data -- بايتات خام اختيارية تُكتَب فور أمر AT (تُستخدَم لحمولات الوصلة الصاعدة الثنائية).

  • timeout -- مهلة الاستجابة، بالميلي ثانية.

  • raise_error -- عندما يكون True، تُحوَّل استجابات الأخطاء إلى استثناءات LoraError؛ وعندما يكون False، تُرجَع الاستجابة الخام إلى المستدعي.