هذا المستودع هو المكان الذي أقوم فيه بتضمين جميع مشاريع تطوير Lora Rhmesh لأطروحتي. أنا أقدم جميع المشاريع داخل مجلد
projects. جميع التطويرات التي تم جمعها من العديد من المشاريع المختلفة المنتشرة في جميع أنحاء الإنترنت ، لكنني أحاول تبسيطها وإعدادها إلى مشروع يعمل ومفهومة.أنا أتطور بشكل أساسي على لوحة ESP32 ، متصلة بشريحة RFM95 Lora. ينقل على 915 ميغاهيرتز. أقوم بتطوير بيئتين ، Arduino IDE ، البرنامج المساعد IO VSCode منصة.
لا تتردد في استخدامها ، والاتصال بي إذا صح التعبير!
يوضح هذا المثال الرسم كيفية إنشاء عميل مراسلة موثوق به مُعالج بسيط مع فئة RHMESH. إنه مصمم للعمل مع الأمثلة الأخرى RF95_MESH_SERVER
#define SELF_ADDRESS NODE3_ADDRESS
#define TARGET_ADDRESS FINAL_ADDRESS
RH_TEST_NETWORK تحديد طوبولوجياك في rhrouter.cpp. اقرأ المزيد في قسم الهيكل القسري [RFM95] ------------- [ESP32]
RESET -------------- GPIO14
NSS/CS -------------- GPIO5
SCK -------------- GPIO18
MOSI -------------- GPIO23
MISO -------------- GPIO19
DIO0 -------------- GPIO2
3.3V -------------- 3.3V
GND -------------- GND


إذا كان لديك مخطط أسلاك مختلف ، فلا تنس تغيير هذه الخطوط في Main.cpp
#define RFM95_CS 5
#define RFM95_RST 14
#define RFM95_INT 2

هذا المثال لطوبولوجيا العقدة 4 ، والتي من المتوقع أن تكون عقدة FINAL_ADDRESS هي العقدة الأخيرة في الشبكة ، محاكاة طوبولوجيا مشتركة تقوم فيها هذه العقدة الأخيرة بمثابة عقدة حدودية متصلة بالإنترنت ، وجمع الرسائل من العقد الأخرى خلال حياتها ، ثم إرسالها إلى السحابة. ستقوم العقدة 1-3 بجمع بيانات المستشعر ثم إرسالها إلى العقدة النهائية ، ويمكن أن تكون العقدة 1-3 عقدة وسيطة لبعضها البعض. لا تتردد في جعل مخطط معالجة مختلف تمامًا.
#define NODE1_ADDRESS 1
#define NODE2_ADDRESS 2
#define NODE3_ADDRESS 3
#define FINAL_ADDRESS 255 // purposefully using the last namber
يمكنك تغيير سلوك العقد الحالي بنشاط عن طريق تغيير هذا الخط. تأكد من تغييره لكل عقدة مختلفة!
const uint8_t selfAddress_ = NODE3_ADDRESS;
const uint8_t targetAddress_ = FINAL_ADDRESS;

بعد اكتشاف مسار للعقدة المستهدفة ، سيتم حفظه كإدخال مسار لجدول التوجيه الخاص به داخل تلك العقدة الفردية. من خلال حفظ العقدة المباشرة التالية التي من المتوقع أن تتمكن من توصيلها بالعقدة الهدف ، حتى كوسيط. لذلك ، في هذا المثال ، تقوم node 2 بحفظ node 1 فقط في إدخال الطريق للاتصال مع node final ، وعدم معرفة ما إذا كانت node 1 هي العقدة الوسيطة الوحيدة ، أو قد يكون هناك المزيد. وبالتالي ، من المتوقع أن يكون لدى node 1 طريق للتواصل مع node final ، في هذا المثال ، سيكون اتصالًا مباشرًا. لا تحتوي node 2 على مسار مباشر إلى node final ، ولكن لديها اتصال مباشر مع node 3
التغيير إلى 915.0 ، 434.0 أو أي تردد آخر ، يجب أن يتطابق مع التكرار Lora CHIP/RX!
#define RF95_FREQ 915.0
باستخدام Mesh ، يكون له متطلبات ذاكرة أكبر بكثير من RH أو Rhrouter فقط ، وقد تحتاج إلى الحد من طول رسالة Max (الأحرف) لمنع حوادث الغريبة. على الرغم من أنه يمكنك تغيير وتجربة أطوال الرسائل عن طريق تغيير هذا
#define RH_MESH_MAX_MESSAGE_LEN 50
يمكنك إضافة أوضاع LORA محددة لوحدة RFM95 عن طريق تحرير rhSetup() . الإعدادات الافتراضية بعد init (بدون أي .set
RHDriver.setTxPower(23, false);
RHDriver.setFrequency(RF95_FREQ);
RHDriver.setCADTimeout(500);
على الرغم من أن هذا المشروع بالذات يعمل على Rhmesh ، والذي يتوقع أن يكون لدى المستخدم طوبولوجيا ديناميكية وسائلة تمامًا ، يمكنك فرض الطرق/الطوبولوجيا. يتطلب القليل من الترميز المتشددين ، يمكنك فحص الكود في rhrouter.cpp (السطر 223-263). يحتوي بالفعل على بعض أمثلة طوبولوجيا ما قبل الصيد التي تجبر التوجيه بطريقة معينة (يقوم بذلك عن طريق إسقاط/عدم معالجة الرسائل التي لا تمتثل للمسار) ، ويجب تحديد الماكرو RH_TEST_NETWORK (قبل الاتصال بـ #include "rhmesh.h") لتفعيل هذا الطوبولوجيا القسرية. يمكنك إضافة الرمز الخاص بك الذي يشبه طوبولوجياك المطلوبة.
...
#ifdef RH_TEST_NETWORK
if (
#if RH_TEST_NETWORK==1
// This network looks like 1-2-3-4
(_thisAddress == 1 && _from == 2)
|| (_thisAddress == 2 && (_from == 1 || _from == 3))
|| (_thisAddress == 3 && (_from == 2 || _from == 4))
|| (_thisAddress == 4 && _from == 3)
#elif RH_TEST_NETWORK==2
// This network looks like 1-2-4
// | | |
// --3--
(_thisAddress == 1 && (_from == 2 || _from == 3))
|| _thisAddress == 2
|| _thisAddress == 3
|| (_thisAddress == 4 && (_from == 2 || _from == 3))
...
سنرسل رسالة إلى عقدة Rhmesh أخرى باستخدام هذا الرمز ، وسيتم اكتشاف طريق إلى الوجهة تلقائيًا. وظيفة الاكتشاف هذه هي النقطة الرئيسية لاستخدام RHMesh ، وهي تقوم تلقائيًا بإنشاء جدول توجيه لهذه العقدة (لمزيد من التحقيق ، تحقق من وظيفة bool doArp(uint8_t address); في RHMesh.h ).
if (RHMeshManager.sendtoWait(reinterpret_cast<uint8_t *>(&msgSend[0]), msgSend.size(), targetAddress_) == RH_ROUTER_ERROR_NONE) {
بعد هذا السطر ، تعني عودة true أننا قد تم تسليم الرسالة بشكل موثوق إلى العقدة التالية ، وقد أرسلت لنا العقدة التالية "ACK". إذا لم يكن هناك ACK بعد وقت معين ، فسيقوم SendTowait بإرجاع false . ملاحظة مهمة هي أن ACK ليس من العقدة الهدف ، ولكن anynode التي تلقت الرسالة بنجاح (بخلاف العقدة الهدف ، هي عقدة وسيطة). حاليًا لا تخبر Rhmesh ما إذا كانت هناك رسالة قد تم استلامها بنجاح إلى العقدة المستهدفة "النهائية". هناك طريقة للتغلب على "ببساطة" إضافة منطق طبقة عالية المستوى/تطبيق إلى العقدة الهدف "النهائية" ، وإرسال رسالة REPLY_TYPE إلى حد ما إلى عقدة المرسل "الأولية" بعد تلقي رسالة ، مثل ACK اصطناعي (لا يتم تطبيق هذه الميزة حاليًا في هذا الريبو).
بعد إرسال رسالة بنجاح ، نتحول إلى RECEIVING_MODE وننتظر رسالة تأتي من عقدة أخرى. في حين أن recvfromAckTimeout نشط ، فإنه سيحتفظ بالأنشطة حتى تصل رسالة ، أو الوصول إلى المهلة.
if (RHMeshManager.recvfromAckTimeout(_msgRcvBuf, (uint8_t *) sizeof(_msgRcvBuf), 3000, &_msgFrom)) {
localVariable_
_tempVariable
globalVariable