إرلانج لإنترنت الأشياء

أدت موجة الاهتمام بالأجهزة الإلكترونية الدقيقة وتفاعلها مع بعضها البعض لتلبية الاحتياجات الصناعية والمنزلية إلى تطوير عدد كبير من المصممين للتطوير على أساس SoC (أنظمة على رقاقة) قوية بما فيه الكفاية ، إلى حد ما مصغرة فيما يتعلق بحلول وحدة التحكم الدقيقة ، ولكنها تحتوي بالفعل على نظام تشغيل كامل. لا يختلف تطوير التطبيقات لمثل هؤلاء المصممين عمليا عن تطوير الخادم المعتاد ، باستثناء أنه يجب أن يظل حد الموارد في الاعتبار.



مع نمو الإنتاجية والقدرات ، تكتسب ممارسة استخدام لغات مترجمة عالية المستوى مثل Lua و Python و JS لتطوير التطبيقات المزيد من الزخم. تخترق بعض اللغات تدريجيًا في "الإخوة الصغار" ، المتحكمون الدقيقون ، ولكن بشكل محدود للغاية.

هناك عدة أسباب لذلك:

  • النماذج الأولية السريعة - مع كل الاحترام الواجب للغة C ، التي تطور بشكل رئيسي المتحكمات الدقيقة ، من الصعب جدًا وصفها بأنها مختصرة. تسمح لك اللغات عالية المستوى بكتابة كود أقل وتبسيط إجراء تغييرات على ما تم كتابته بالفعل ، وهو أمر مهم جدًا في مرحلة النموذج الأولي ؛
  • إدارة تلقائية للذاكرة واستخلاص لآليات الحساب المعقدة - أعتقد أنها لا تحتاج إلى تعليقات ، حيث تتحول كلتا العمليتين اليدويتين مع حجم مشروع كاف إلى مصدر للكثير من الصداع ؛
  • تبسيط التصحيح والاختبار - من السهل التحقق من التعليمات البرمجية المفسرة على محطة العمل قبل وقت الاختبار الميداني ؛
  • صراع مع التعقيد - غالبًا ما تؤدي الإنتاجية الكبيرة إلى ظهور رغبة عملية واقعية في دفع المزيد من المعالجة المسبقة والتحليل إلى الجهاز ، مما لا يضيف البساطة إلى التطوير.

للأسف ، عليك أن تدفع مقابل جميع وسائل الراحة. في هذه الحالة ، يكون سعر الملاءمة هو أثمن الموارد والأداء وحجم الرمز (في كثير من الحالات عليك أن تحمل بيئة وقت تشغيل ضخمة إلى حد ما). لذلك ، يعد التطبيق الميداني للغات عالية المستوى في SoC و SoM أمرًا غامضًا ، وفي بعض الأماكن ، حل وسط.

نحن نستخدم لغة Erlang للتطوير ، ونطبقها للغرض المقصود منها (إنشاء تطبيقات خادم ومستوى تحكم) ، وتطبيقات الويب غير المعتادة. لذلك ، نشأت فكرة استخدام البنية التحتية لهذه اللغة لإنشاء حلول إنترنت الأشياء قبل وقت طويل من ظهور اللوحات التي يمكن أن يعمل عليها وقت تشغيل Erlang دون مشاكل.

كانت أسباب استخدام Erlang كثيرة ، والأكثر أهمية:

  • يعتبر Erlang مناسبًا جدًا للتحليل وإنشاء تسلسلات ثنائية. تسمح مطابقة الأنماط المقترنة بمعالجة بيانات البتات بتنفيذ البروتوكولات الثنائية بسرعة كبيرة وبدون كلمات ؛
  • الافتقار إلى المتغيرات العالمية وعدم القدرة على التغيير لمعظم البيانات - يسمح لك بالكتابة ، وليس أقل أهمية ، الحفاظ على تطبيقات موثوقة يصعب فيها تغيير شيء خاطئ عن طريق الخطأ ؛
  • عمليات المراسلة خفيفة الوزن التي تشبه إلى حد كبير ما يجب على المطورين المضمنين التعامل معه. في جوهرها ، فهي إجراء التهيئة وإجراء يعالج الرسائل الواردة في حلقة لا نهائية ، وتغيير الحالة الداخلية. إنه مشابه جدًا لـ Arduino ، فقط يمكن أن يكون هناك العديد من العمليات ويعملون بالتوازي ، بالإضافة إلى ذلك ، في الفترة الفاصلة بين الرسائل ، يمكن تغيير إجراء المعالجة على الفور (إعادة تحميل الرمز الساخن) ، وهو أمر مريح للغاية عندما تحتاج إلى إصلاح الأخطاء الطفيفة أو تعديل السلوك ؛
  • أعتقد أن البيئة المعزولة وتخصيص الذاكرة التلقائي لا تحتاج إلى شرح ؛
  • عبر النظام الأساسي - يمكن تجميع كود البايت لوقت تشغيل ERTS على جهاز المطور ، ثم نقله إلى الجهاز المستهدف دون مشاكل ؛
  • أدوات استبطان ممتازة - القدرة على الاتصال بتطبيق قيد التشغيل عبر الشبكة ومعرفة أنه يبطئ كثيرًا ما تكون مفيدة جدًا في كثير من الأحيان.

أول لوحة عمل حاولنا فيها إرلانج كانت Carambola 2 من المطورين الليتوانيين من 8 أجهزة ، تم تجميعها على شريحة AR9331 الشهيرة. الإصدار الأول من هذا المنتدى ، للأسف ، لم يكن لديه ذاكرة فلاش كافية لتناسب وقت التشغيل. لكن الإصدار الثاني سمح لنفسه بالفعل باستيعاب ERTS وتطبيق صغير.



تم تنفيذ التثبيت بطريقة كلاسيكية لهذا النوع من الأجهزة - تجميع صورة OpenWRT تحتوي على Erlang ، تليها وميضها في ذاكرة فلاش للجهاز. أدى الإطلاق الأول للبيئة ، للأسف ، إلى خيبة الأمل - كل شيء معلق. لقد شرحت بالفعل أسباب ذلك في مؤتمر InoThings 2018 ، ولكن للأسف ، كما اتضح لاحقًا ، ضلل زملائي من خلال تسمية مصدر هذا السلوك عن طريق الخطأ.

سأعيد روايتها لفترة وجيزة. عند العمل مع الملفات ، يستخدم الجهاز الظاهري ERTS نوع off_t ، الذي يتم حساب حجمه في التوزيع عندما يتم تكوين التجميع تلقائيًا (إذا تم تشغيله على النظام الأساسي المستهدف) أو يتم استبداله من بيئة التجميع المتقاطع ، كما حدث في حالة OpenWRT. ليس من الواضح لماذا ، ولكن في إعدادات معالجات MIPS ومشتقاتها في ملف تكوين التجميع ضعف حجمها في الواقع. لن تنشأ المشكلة إذا لم يستخدم رمز الجهاز الظاهري توجيهات المعالج الأولي مثل

#if SIZEOF_OFF_T == 4 

وفحص عادي في الكود (أظن أن نتيجة التجميع النهائية ستكون هي نفسها ، ولكن لم يكن هناك ما يكفي من الصمامات للتحقق):

 if (sizeof(off_t) == 4) { 

ونتيجة لذلك ، جمعت ERTS في التكرار الأول عند محاولة قراءة ملف ~ / .erlang.cookie (نوع من كلمة المرور لتحديد الهوية أثناء تفاعل الشبكة) في البداية بنجاح تلقى القمامة بترتيب عالي وتعطلت مع انفجار .

يمكن تنزيل حزمة التصحيح والحزمة مع الإصدار قبل الأخير من ERTS لـ OpenWRT من GitHub . بالإضافة إلى ذلك ، لم يتم ملاحظة المشاكل حتى الآن ، وعمل كل شيء كما هو متوقع.

النظام الأساسي الثاني للأجهزة الذي جربناه Erlang كان مصمم LinkIt Smart 7688 من Mediatek و SeeedStudio ، المصمم خصيصًا للنماذج الأولية السريعة وتعلم الأساسيات. هذه اللوحة هي ببساطة تأليه الفسق من حيث الموارد - نما تواتر نواة MIPS بنسبة 1.5 مرة ، وزيادة ذاكرة الوصول العشوائي (بالنسبة لـ ERTS من المهم ، GC لا تتلاشى) والمزيد من الذاكرة المحمولة ، بالإضافة إلى وجود بطاقة microSD وإمكانية استخدام المعالج Atmel المشترك Atmega 32U4 في إصدار Duo للعمل مع الأجهزة الطرفية.

بشكل عام ، كانت المنصة مناسبة جدًا لمواصلة الولائم ، ويسمح لك وجود أجهزة توصيل إضافية متصلة بدون لحام بتجميع مقعد اختبار بسرعة وشروط على ركبتك.

تأتي المنصة مع برنامج مع واجهة الويب الخاصة بها ، بالإضافة إلى مكتبات Python و NodeJS للتطوير. لم يتغير النظام البيئي للتجميع - لا يزال OpenWRT. إذا وجدت لسبب ما كل هذا التنوع غير ضروري ، فعندئذ يوجد في المستودع أعلاه حزم تحتوي على مجموعة صغيرة من المكونات المطلوبة . بعد التجميع ، تتم كتابة صورة الفلاش على الجهاز وبعد إعادة التشغيل ، يمكنك استخدام REPL بأمان.

لبناء تطبيقات على Erlang لـ IoT ، يجب حل مشكلة معمارية واحدة.

تم تصميم اللغة وتطويرها مع التركيز على ما سيكون بمثابة طائرة تحكم ، أي طبقة التحكم ، أثناء العمل بالحديد كان من المفترض أن يكون من خلال FFI. يتم توفير ثلاثة أنواع من التفاعل لهذا:

  1. المنافذ (المنافذ) - عمليات عمل منفصلة مكتوبة بأي لغة ، والتفاعل الذي يحدث من خلال تدفقات الإدخال / الإخراج. يمكن إعادة تشغيلها في حالة السقوط ، ولكن بسبب طريقة التفاعل ، فإن إنتاجيتها من حيث الاتصال صغيرة (ومع ذلك ، ستكون كافية بالنسبة لنا) ؛
  2. وظائف NIF - تبدو مثل الوظائف القياسية للغة ، ولكن نداءهم يولد تنفيذ التعليمات البرمجية المترجمة في مساحة وقت التشغيل. في حالة حدوث خطأ ، يمكنهم سحب الجهاز الظاهري بأكمله خلفهم.
  3. العقدة C - عندما يتم العمل بأكمله في عملية منفصلة ، ويتم التفاعل كما هو الحال مع بيئة تشغيل تعمل بشكل منفصل عبر الشبكة. لن نفكر في هذا الخيار بسبب التكاليف العامة الكبيرة بما يكفي في إطار جهاز واحد ضعيف.

المعضلة هي: يمكننا فقط نقل الأشياء إلى FFI (أي دعم GPIO و I2C و SPI و PWM و UART وما إلى ذلك) ، ويمكننا التفاعل مباشرة مع أجهزة الاستشعار والأجهزة الأخرى على Erlang ، أو على العكس من ذلك ، لنقل برامج تشغيل الجهاز بالكامل إلى رمز الوحدات الخارجية ، وترك التطبيق لتلقي البيانات الأولية ومعالجتها ، في هذه الحالة ، قد يكون من المنطقي استخدام الرمز المكتوب بالفعل.

قررنا استخدام الخيار الأول. هناك عدة أسباب لذلك:

  • لأننا نستطيع ؛
  • كما ذكرت من قبل ، يأتي Erlang مع أدوات قوية بما يكفي لتجميع وتفكيك المتواليات الثنائية ، في حين أنها عملية حسابية بسيطة للغاية ، والتي تسمح لك بعدم القلق بشأن الحماية ضد التدفقات وغيرها من السحر المستخدم في معالجة النتائج. ليس هذا فزاعة سحرية ، لكنه يؤثر على الصدمات الجديدة بشكل مروع.
  • بشكل حدسي ، بدا أن السائقين في لغة عالية المستوى سيكونون أبسط وأكثر موثوقية (عملية متعطلة ستعيد تشغيل المشرف ، مما سيؤدي إلى إعادة تهيئة الجهاز المتحكم به).

لذلك ، تم العثور على مكتبة ErlangALE بسرعة ، والتي تحتوي على دعم تم تنفيذه بالفعل لـ GPIO و I2C و SPI من خلال واجهات kernel ، وقد قام مطورو منصة الأجهزة بدورهم بالفعل برعايتهم. تم اختبار مكتبة العمل مع UART بالفعل ، بالإضافة إلى أننا أضفنا erlexec ، وهو تطبيق يتيح لك إنشاء عمليات نظام التشغيل وإدارتها.

استخدمت جميع هذه التطبيقات المنافذ (العمليات الثنائية التي تم إطلاقها بشكل منفصل) للعمل مع المعدات ونظام التشغيل ، الأمر الذي يتطلب دعمًا جامعًا للغات C و C ++ ، والتي تمت كتابة نص برمجي متقن له تكوين بيئة البناء لاستخدام المترجمات الضرورية.

لاختبار القرارات التي اتخذناها ، قمنا بتجميع جهاز بسيط من LinkIt Smart 7866 ، وجهازي I2C (درجة الحرارة BMP280 ومستشعر الضغط و 128 شاشة OLED من 64 بكسل) ووحدة USB GPS ترسل البيانات عبر UART. تم اختبار GPIO على LED على اللوحة ، وهو يعمل ، وبدا توصيل شاشة SPI غير ضروري في هذه المرحلة من التعقيدات.



اتضح أنه تطبيق مضغوط وبسيط إلى حد ما ، يمكن عرض شفرة المصدر على Github.

لن أخوض في أجزاء التعليمات البرمجية ، ولكن أحاول أن أصف في نظرة عامة كيفية عمل التطبيق.

يتم تصنيع برامج تشغيل جميع الأجهزة في شكل عمليات gen_server ، وهذا مناسب لأنه يسمح لك بإضافة معلمات إضافية ، وأحيانًا حالة الجهاز إلى الحالة. يمكن رؤية هذا الأخير في مثال uart_gps - تصل البيانات من UART بشكل غير متزامن ، ويتم تحليلها بواسطة محلل NMEA0183 ، ويتم كتابة النتائج إلى حالة العملية ، حيث يتم الحصول عليها من خلال الطلب.

تم وصف الدورة الرئيسية للتطبيق في وحدة gps_temp_display - في كل ثانية تقرأ العملية بيانات GPS وتطلب حالة درجة الحرارة والضغط من BMP280 وتعرضها على شاشة OLED. من أجل الاهتمام ، يمكنك إلقاء نظرة على برامج تشغيل الشاشة وأجهزة الاستشعار BMP280 - تحول كل شيء بإيجاز شديد ، 150-170 خطًا لكل وحدة.

بشكل عام ، استغرقت المهمة المذكورة أعلاه (كتابة كود السائق ، ودمج كل شيء في تطبيق واحد ، وتجميع واختبار) حوالي أربع أمسيات ، ساعتين في المتوسط ​​، أي بشكل دقيق ، بضعة أيام عمل. يبدو لي شخصيًا أن هذا مؤشر جيد لمحاولة استخدام Erlang في التطبيقات المضمنة الأكثر تعقيدًا والجدية التي لا تتطلب قيودًا صارمة في الوقت الفعلي.

بالطبع ، محاولاتنا لاستخدام Erlang للأنظمة المضمنة ليست بأي حال من الأحوال هي الوحيدة. هناك العديد من المشاريع المثيرة للاهتمام في هذا الصدد:

  • nerves-project.org - يهدف إلى إنشاء نظام بيئي مضمن يعتمد على إكسير ؛
  • www.grisp.org - نهج أكثر راديكالية ، يتضمن إطلاق ERTS مباشرة على الأجهزة (نظام Erlang المعدني المعدني) ؛
  • github.com/bettio/AtomVM و github.com/cloudozer/ling - محاولات لإنشاء نسخة مضغوطة من ERTS ، مناسبة للاستخدام في وحدات التحكم الدقيقة وضعف SoC / SoM.

Source: https://habr.com/ru/post/ar417245/


All Articles