Merge branch 'main' into patch-9

pull/97/head
Jim Bennett 4 years ago committed by GitHub
commit c2f06740a1
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23

@ -5,6 +5,7 @@
"Geospatial",
"Kbps",
"Mbps",
"SSML",
"Seeed",
"Siri",
"Twilio",

@ -0,0 +1,284 @@
# <div dir="rtl"> مقدمة لإنترنت الأشياء </div>
![A sketchnote overview of this lesson](../../../../sketchnotes/lesson-1.png)
> <div dir="rtl"> خريطة من <a href="https://github.com/nitya">Nitya Narasimhan</a> </div>
> <div dir="rtl"> اضغط على الصورة لتكبيرها </div>
## <div dir="rtl"> اختبار ما قبل المحاضرة </div>
[<div dir="rtl"> اختبار ما قبل المحاضرة </div>](https://brave-island-0b7c7f50f.azurestaticapps.net/quiz/1)
## <div dir="rtl"> المقدمة </div>
<div dir="rtl"> يغطي هذا الدرس بعض الموضوعات التمهيدية حول إنترنت الأشياء ، ويساعدك على إعداد أجهزتك. </div>
<div dir="rtl"> سنغطي في هذا الدرس: </div>
<div dir="rtl">
- [ ما هو انترنت الأشياء ](#what-is-the-internet-of-things)
- [الأجهزة المتعلقة بانترنت الأشياء](#iot-devices)
- [قم بإعداد جهازك](#set-up-your-device)
- [تطبيقات انترنت الأشياء](#applications-of-iot)
- [أمثلة على أجهزة إنترنت الأشياء التي قد تكون موجودة حولك](#examples-of-iot-devices-you-may-have-around-you)
</div>
## <div dir="rtl"> ما هو "انترنت الأشياء"؟ </div>
<div dir="rtl"> مصطلح "إنترنت الأشياء" ابتكره
<a href="https://wikipedia.org/wiki/KevinAshton">Kevin Ashton</a>
في عام 1999 ، للإشارة إلى توصيل الإنترنت بالعالم المادي عبر أجهزة الاستشعار. منذ ذلك الحين ، تم استخدام المصطلح لوصف أي جهاز يتفاعل مع العالم المادي من حوله ، إما عن طريق جمع البيانات من أجهزة الاستشعار ، أو توفير تفاعلات في العالم الحقيقي عبر المشغلات (الأجهزة التي تقوم بشيء مثل تشغيل مفتاح أو إضاءة LED ) ، متصلة بشكل عام بأجهزة أخرى أو بالإنترنت. </div>
> <div dir="rtl"> المستشعرات تجمع المعلومات من العالم ، مثل قياس السرعة أو درجة الحرارة أو الموقع. </div>
>
> <div dir="rtl"> المشغلات تحول الإشارات الكهربائية إلى تفاعلات في العالم الحقيقي مثل تشغيل مفتاح أو تشغيل الأضواء أو إصدار أصوات أو إرسال إشارات تحكم إلى أجهزة أخرى ، على سبيل المثال لتشغيل مقبس طاقة. </div>
<div dir="rtl">إن إنترنت الأشياء كمجال تقني هو أكثر من مجرد أجهزة - فهو يشمل الخدمات المستندة إلى السحابة التي يمكنها معالجة بيانات المستشعر ، أو إرسال طلبات إلى المشغلات المتصلة بأجهزة إنترنت الأشياء. ويشمل أيضًا الأجهزة التي لا تحتوي على اتصال بالإنترنت أو لا تحتاج إليه ، وغالبًا ما يشار إليها باسم الأجهزة المتطورة. هذه هي الأجهزة التي يمكنها معالجة بيانات الاستشعار والاستجابة لها بنفسها ، وعادةً ما تستخدم نماذج الذكاء الاصطناعي المدربة في السحابة.</div>
<div dir="rtl">إنترنت الأشياء هو مجال تكنولوجي سريع النمو. تشير التقديرات إلى أنه بحلول نهاية عام 2020 ، تم نشر 30 مليار جهاز إنترنت الأشياء وتوصيلها بالإنترنت. بالنظر إلى المستقبل ، تشير التقديرات إلى أنه بحلول عام 2025 ، ستجمع أجهزة إنترنت الأشياء ما يقرب من 80 زيتابايت من البيانات ، أو 80 تريليون جيجابايت. هذا كثير من البيانات!</div>
![A graph showing active IoT devices over time, with an upward trend from under 5 billion in 2015 to over 30 billion in 2025](../../../../images/connected-iot-devices.svg)
<div dir="rtl">✅ قم بإجراء القليل من البحث: ما مقدار البيانات التي تم إنشاؤها بواسطة أجهزة إنترنت الأشياء المستخدمة بالفعل ، وكم يتم إهدارها؟ لماذا يتم تجاهل الكثير من البيانات؟ </div>
<div dir="rtl">
هذه البيانات هي مفتاح نجاح إنترنت الأشياء. لكي تكون مطورًا ناجحًا لإنترنت الأشياء ، فأنت بحاجة إلى فهم البيانات التي تحتاج إلى جمعها ، وكيفية جمعها ، وكيفية اتخاذ القرارات بناءً عليها ، وكيفية استخدام هذه القرارات للتفاعل مع العالم المادي إذا لزم الأمر.</div>
## <div dir="rtl">الأجهزة المتعلقة بانترنت الأشياء</div>
<div dir="rtl">
يرمز T في إنترنت الأشياء إلى الأشياء - الأجهزة التي تتفاعل مع العالم المادي من حولها إما عن طريق جمع البيانات من أجهزة الاستشعار ، أو توفير تفاعلات واقعية عبر المشغلات.
عادةً ما تكون الأجهزة المخصصة للإنتاج أو الاستخدام التجاري ، مثل أجهزة تتبع اللياقة البدنية للمستهلكين أو أجهزة التحكم في الآلات الصناعية ، مصنوعة خصيصًا. يستخدمون لوحات دوائر مخصصة ، وربما حتى معالجات مخصصة ، مصممة لتلبية احتياجات مهمة معينة ، سواء كانت صغيرة بما يكفي لتناسب معصمك ، أو متينة بما يكفي للعمل في درجات حرارة عالية ، أو ضغط مرتفع ، أو بيئة مصنع عالية الاهتزاز.
بصفتك مطورًا إما يتعلم عن إنترنت الأشياء أو يصنع نموذجًا أوليًا للجهاز ، فستحتاج إلى البدء بمجموعة أدوات التطوير. هذه أجهزة إنترنت الأشياء للأغراض العامة مصممة للمطورين لاستخدامها ، غالبًا مع ميزات لن تراها على جهاز إنتاج ، مثل مجموعة من المسامير الخارجية لتوصيل المستشعرات أو المشغلات بها ، أو الأجهزة لدعم التصحيح ، أو الموارد الإضافية التي سيضيف تكلفة غير ضرورية عند إجراء عملية تصنيع كبيرة.
تنقسم مجموعات المطورين هذه عادةً إلى فئتين - المتحكمات الدقيقة وأجهزة الكمبيوتر أحادية اللوحة. سيتم تقديم هذه هنا ، وسنتناول المزيد من التفاصيل في الدرس التالي.
>💁يمكن أيضًا اعتبار هاتفك جهاز إنترنت الأشياء للأغراض العامة ، مع أجهزة استشعار ومحركات مدمجة ، مع تطبيقات مختلفة تستخدم المستشعرات والمشغلات بطرق مختلفة مع خدمات سحابية مختلفة. يمكنك أيضًا العثور على بعض البرامج التعليمية لإنترنت الأشياء التي تستخدم تطبيق الهاتف كجهاز إنترنت الأشياء.
</div>
</br>
### <div dir="rtl">المتحكم الدقيق</div>
<div dir="rtl">
المتحكم الدقيق (يشار إليه أيضًا باسم MCU ، اختصارًا لوحدة التحكم الدقيقة) هو جهاز كمبيوتر صغير يتكون من:
🧠 واحدة أو أكثر من وحدات المعالجة المركزية (CPUs) - "عقل" المتحكم الدقيق الذي يدير برنامجك
💾 الذاكرة (ذاكرة الوصول العشوائي وذاكرة البرنامج) - حيث يتم تخزين البرنامج والبيانات والمتغيرات الخاصة بك
🔌 اتصالات الإدخال / الإخراج القابلة للبرمجة (I / O) - للتحدث إلى الأجهزة الطرفية الخارجية (الأجهزة المتصلة) مثل المستشعرات والمشغلات
عادةً ما تكون وحدات التحكم الدقيقة أجهزة حوسبة منخفضة التكلفة ، حيث ينخفض ​​متوسط ​​أسعار الأجهزة المستخدمة في الأجهزة المخصصة إلى حوالي 0.50 دولار أمريكي ، وبعض الأجهزة رخيصة مثل 0.03 دولار أمريكي. يمكن أن تبدأ مجموعات المطورين بسعر منخفض يصل إلى 4 دولارات أمريكية ، مع ارتفاع التكاليف كلما أضفت المزيد من الميزات. <a href="https://www.seeedstudio.com/Wio-Terminal-p-4509.html">محطة Wio</a>, مجموعة مطور متحكم من <a href="https://www.seeedstudio.com">Seeed studios</a> تحتوي على أجهزة استشعار ومحركات واي فاي وشاشة تكلف حوالي 30 دولارًا أمريكيًا.
</div>
![A Wio Terminal](../../../../images/wio-terminal.png)
> <div dir="rtl">💁 عند البحث في الإنترنت عن المتحكمات الدقيقة ، احذر من البحث عن المصطلح MCU لأن هذا سيعيد لك الكثير من النتائج ل Marvel السينمائي ، وليس للمتحكمات الدقيقة.</div>
<div dir="rtl">
تم تصميم وحدات التحكم الدقيقة بحيث تتم برمجتها للقيام بعدد محدود من المهام المحددة للغاية ، بدلاً من أن تكون أجهزة كمبيوتر للأغراض العامة مثل أجهزة الكمبيوتر الشخصية أو أجهزة Mac. باستثناء سيناريوهات محددة للغاية ، لا يمكنك توصيل الشاشة ولوحة المفاتيح والماوس واستخدامها في مهام الأغراض العامة.
عادة ما تأتي مجموعات مطوري وحدات التحكم الدقيقة بأجهزة استشعار ومشغلات إضافية على متنها. تحتوي معظم اللوحات على واحد أو أكثر من مصابيح LED التي يمكنك برمجتها ، بالاضافة الى الأجهزة الأخرى مثل المقابس القياسية لإضافة المزيد من أجهزة الاستشعار أو المشغلات باستخدام أنظمة بيئية مختلفة للمصنعين ، أو أجهزة استشعار مدمجة (عادةً ما تكون الأكثر شيوعًا مثل مستشعرات درجة الحرارة). تحتوي بعض وحدات التحكم الدقيقة على اتصال لاسلكي مدمج مثل Bluetooth أو WiFi ، أو تحتوي على وحدات تحكم دقيقة إضافية على اللوحة لإضافة هذا الاتصال.
</div>
> <div dir="rtl">💁 عادة ما يتم برمجة المتحكمات الدقيقة في C / C ++. </div>
### <div dir="rtl"> أجهزة كمبيوتر أحادية اللوحة</div>
<div dir="rtl"> الكمبيوتر أحادي اللوحة هو جهاز حوسبة صغير يحتوي على جميع عناصر الكمبيوتر الكامل الموجودة على لوحة صغيرة واحدة. هذه هي الأجهزة التي لها مواصفات قريبة من سطح المكتب أو الكمبيوتر المحمول أو جهاز Mac ، وتعمل بنظام تشغيل كامل ، ولكنها صغيرة ، وتستخدم طاقة أقل ، وأرخص بكثير.</div>
![A Raspberry Pi 4](../../../../images/raspberry-pi-4.jpg)
***Raspberry Pi 4. Michael Henzler / [Wikimedia Commons](https://commons.wikimedia.org/wiki/Main_Page) / [CC BY-SA 4.0](https://creativecommons.org/licenses/by-sa/4.0/)***
<div dir="rtl">
يعد Raspberry Pi أحد أشهر أجهزة الكمبيوتر أحادية اللوحة.
مثل وحدة التحكم الدقيقة ، تحتوي أجهزة الكمبيوتر أحادية اللوحة على وحدة معالجة مركزية وذاكرة ودبابيس إدخال / إخراج ، ولكنها تحتوي على ميزات إضافية مثل شريحة رسومات للسماح لك بتوصيل الشاشات ومخرجات الصوت ومنافذ USB مثل كاميرات الويب أو وحدات التخزين الخارجية. يتم تخزين البرامج على بطاقات SD أو محركات أقراص ثابتة بالاضافة الى نظام التشغيل ، بدلاً من شريحة ذاكرة مدمجة في اللوحة.
</div>
> <div dir="rtl">🎓 يمكنك التفكير في الكمبيوتر أحادي اللوحة كإصدار أصغر وأرخص من الكمبيوتر الشخصي أو جهاز Mac الذي تقرأ عليه ، مع إضافة دبابيس GPIO (إدخال / إخراج للأغراض العامة) للتفاعل مع المستشعرات والمحركات.</div>
<div dir="rtl">أجهزة الكمبيوتر أحادية اللوحة هي أجهزة كمبيوتر كاملة الميزات ، لذا يمكن برمجتها بأي لغة. عادةً ما تتم برمجة أجهزة إنترنت الأشياء بلغة Python.</div>
</br>
### <div dir="rtl"> اختيارات الأجهزة لبقية الدروس</div>
<div dir="rtl">تتضمن جميع الدروس اللاحقة مهام باستخدام جهاز إنترنت الأشياء للتفاعل مع العالم والتواصل مع السحابة. يدعم كل درس 3 خيارات للأجهزة - Arduino (باستخدام Seeed Studios Wio Terminal) ، أو كمبيوتر لوحة واحدة ، إما جهاز (Raspberry Pi 4) ، أو جهاز كمبيوتر افتراضي أحادي اللوحة يعمل على الكمبيوتر الشخصي أو جهاز Mac.</div>
يمكنك أن تقرأ عن الأجهزة اللازمة لإكمال جميع المهام في ملف [hardware guide](../../../../hardware.md)
> <div dir="rtl">💁 لا تحتاج إلى شراء أي جهاز إنترنت الأشياء لإكمال المهام ، يمكنك القيام بكل شيء باستخدام جهاز كمبيوتر افتراضي أحادي اللوحة. </div>
<div dir="rtl">تحديد الأجهزة التي تختارها متروك لك - يعتمد ذلك على ما لديك إما في المنزل أو في مدرستك ، ولغة البرمجة التي تعرفها أو تخطط لتعلمها. سيستخدم كلا النوعين من الأجهزة نفس نظام المستشعر البيئي ، لذلك إذا بدأت في مسار واحد ، يمكنك التغيير إلى الآخر دون الحاجة إلى استبدال معظم المجموعة. سيكون الكمبيوتر الافتراضي أحادي اللوحة مكافئًا للتعلم على Raspberry Pi ، حيث يمكن نقل معظم الشفرة إلى Pi إذا حصلت في النهاية على جهاز ومستشعرات.</div>
</br>
### <div dir="rtl"> مجموعة مطوري Arduino </div>
<div dir="rtl"> إذا كنت مهتمًا بتعلم تطوير وحدة التحكم الدقيقة ، فيمكنك إكمال المهام باستخدام جهاز Arduino. ستحتاج إلى فهم أساسي لبرمجة C / C ++ ، حيث أن الدروس ستعلم فقط الكود ذي صلة بإطار عمل Arduino ، وأجهزة الاستشعار والمشغلات المستخدمة ، والمكتبات التي تتفاعل مع السحابة. </div>
<div dir="rtl"> ستستخدم الواجبات <a href="https://www.seeedstudio.com/Wio-Terminal-p-4509.html">Visual Studio Code</a> مع <a href="https://www.seeedstudio.com/Wio-Terminal-p-4509.html">امتداد PlatformIO لتطوير وحدة التحكم الدقيقة</a>. يمكنك أيضًا استخدام Arduino IDE إذا كنت من ذوي الخبرة في هذه الأداة ، حيث لن يتم توفير الإرشادات.</div>
</br>
### <div dir="rtl"> مجموعة مطوري الكمبيوتر أحادية اللوحة </div>
<div dir="rtl">
إذا كنت مهتمًا بتعلم تطوير إنترنت الأشياء باستخدام أجهزة كمبيوتر أحادية اللوحة ، فيمكنك إكمال المهام باستخدام Raspberry Pi ، أو جهاز افتراضي يعمل على جهاز الكمبيوتر أو جهاز Mac.
ستحتاج إلى فهم أساسي لبرمجة Python ، حيث ستعلم الدروس فقط التعليمات البرمجية ذات الصلة بالمستشعرات والمشغلات المستخدمة والمكتبات التي تتفاعل مع السحابة.
</div>
> <div dir="rtl">💁 إذا كنت تريد تعلم البرمجة في Python ، فراجع سلسلتي الفيديو التاليين:
>
>* [بايثون للمبتدئين](https://channel9.msdn.com/Series/Intro-to-Python-Development?WT.mc_id=academic-17441-jabenn)
> * [ المزيد من بايثون للمبتدئين ](https://channel9.msdn.com/Series/More-Python-for-Beginners?WT.mc_id=academic-7372-jabenn)
</div>
<div dir="rtl">
الواجبات ستستخدم <a href="https://www.seeedstudio.com/Wio-Terminal-p-4509.html">Visual Studio Code</a>
إذا كنت تستخدم Raspberry Pi ، فيمكنك إما تشغيل Pi الخاص بك باستخدام إصدار سطح المكتب الكامل من Raspberry Pi OS ، والقيام بكل الترميز مباشرة على Pi باستخدام <a href="https://code.visualstudio.com/docs/setup/raspberry-pi?WT.mc_id=academic-17441-jabenn">the Raspberry Pi OS version of VS Code</a> ، أو قم بتشغيل Pi من جهاز الكمبيوتر أو جهاز Mac باستخدام VS Code مع <a href="https://code.visualstudio.com/docs/remote/ssh?WT.mc_id=academic-17441-jabenn">Remote SSH extension</a> التي يتيح لك الاتصال بـ Pi الخاص بك وتحرير التعليمات البرمجية وتصحيحها وتشغيلها كما لو كنت تقوم بالتشفير عليها مباشرةً.
إذا كنت تستخدم خيار الجهاز الظاهري ، فستقوم بالتشفير مباشرة على جهاز الكمبيوتر الخاص بك. بدلاً من الوصول إلى المستشعرات والمشغلات ، ستستخدم أداة لمحاكاة هذا الجهاز لتوفير قيم أجهزة الاستشعار التي يمكنك تحديدها ، وإظهار نتائج المشغلات على الشاشة.
</div>
### <div dir="rtl"> قم بإعداد جهازك </div>
<div dir="rtl"> قبل أن تبدأ في برمجة جهاز إنترنت الأشياء الخاص بك ، ستحتاج إلى إجراء قدر صغير من الإعداد. اتبع التعليمات ذات الصلة أدناه بناءً على الجهاز الذي ستستخدمه. </div>
> <div dir="rtl">💁 إذا لم يكن لديك جهاز بعد ، فارجع إلى </div>
>
>[hardware guide](../../../../hardware.md) للمساعدة في تحديد الجهاز الذي ستستخدمه والأجهزة الإضافية التي تحتاج إلى شرائها. لا تحتاج إلى شراء أجهزة ، حيث يمكن تشغيل جميع المشاريع على أجهزة افتراضية.
<div dir="rtl">
تتضمن هذه التعليمات ارتباطات إلى مواقع ويب تابعة لجهات خارجية من منشئي الأجهزة أو الأدوات التي ستستخدمها. هذا للتأكد من أنك تستخدم دائمًا أحدث الإرشادات للأدوات والأجهزة المختلفة.
اعمل من خلال الدليل ذي الصلة لإعداد جهازك وإكمال مشروع "Hello World". ستكون هذه هي الخطوة الأولى في إنشاء ضوء ليلي لإنترنت الأشياء على الدروس الأربعة .
* [ وحدة Arduino - Wio ](../wio-terminal.md)
* [كمبيوتر ذو لوحة واحدة - Raspberry Pi](../pi.md)
* [كمبيوتر ذو لوحة واحدة - جهاز افتراضي](../virtual-device.md)
</div>
### <div dir="rtl"> تطبيقات إنترنت الأشياء </div>
<div dir="rtl">يغطي إنترنت الأشياء مجموعة كبيرة من حالات الاستخدام عبر مجموعات قليلة:
* انترنت الاشياء المستهلك
* إنترنت الأشياء التجاري
* إنترنت الأشياء الصناعي
* انترنت الاشياء البنية التحتية
</div>
<div dir="rtl">✅ قم ببعض البحث: لكل مجال من المجالات الموضحة أدناه ، ابحث عن مثال ملموس واحد لم يرد في النص.</div>
### <div dir="rtl"> انترنت الاشياء المستهلك </div>
<div dir="rtl">
يشير IoT للمستهلكين إلى أجهزة IoT التي سيشتريها المستهلكون ويستخدمونها في المنزل. بعض هذه الأجهزة مفيدة بشكل لا يصدق ، مثل مكبرات الصوت الذكية وأنظمة التدفئة الذكية والمكانس الكهربائية الآلية. البعض الآخر مشكوك فيه في فائدته ، مثل الصنابير التي يتم التحكم فيها بالصوت والتي تعني بعد ذلك أنه لا يمكنك إيقاف تشغيلها لأن التحكم الصوتي لا يمكنه سماع صوت المياه الجارية.
تعمل أجهزة إنترنت الأشياء للمستهلكين على تمكين الأشخاص من تحقيق المزيد في محيطهم ، وخاصة المليار شخص من ذوي الإعاقة. يمكن للمكانس الكهربائية الروبوتية توفير أرضيات نظيفة للأشخاص الذين يعانون من مشاكل في الحركة والذين لا يستطيعون تنظيف أنفسهم ، وتسمح الأفران التي يتم التحكم فيها بالصوت للأشخاص ذوي الرؤية المحدودة أو التحكم في المحرك بتسخين أفرانهم بصوتهم فقط ، ويمكن أن تسمح أجهزة المراقبة الصحية للمرضى بمراقبة الحالات المزمنة بأنفسهم بمزيد من الانتظام والمزيد من التحديثات التفصيلية عن ظروفهم. أصبحت هذه الأجهزة منتشرة في كل مكان حتى أن الأطفال الصغار يستخدمونها كجزء من حياتهم اليومية ، على سبيل المثال الطلاب الذين يقومون بالتعليم الافتراضي أثناء جائحة COVID يضبطون أجهزة ضبط الوقت على الأجهزة المنزلية الذكية لتتبع أعمالهم المدرسية أو أجهزة الإنذار لتذكيرهم باجتماعات الفصل القادمة.
</div>
<div dir="rtl">✅ ما هي أجهزة IoT الاستهلاكية التي لديك أو في منزلك؟ </div>
</br>
### <div dir="rtl">انترنت الأشياء التجاري </div>
<div dir="rtl">
يغطي إنترنت الأشياء التجاري استخدام إنترنت الأشياء في مكان العمل. في مكتب ما ، قد يكون هناك أجهزة استشعار إشغال وكاشفات حركة لإدارة الإضاءة والتدفئة لإبقاء الأضواء والتدفئة فقط عند عدم الحاجة إليها ، مما يقلل التكلفة وانبعاثات الكربون. في المصنع ، يمكن لأجهزة إنترنت الأشياء مراقبة مخاطر السلامة مثل عدم ارتداء العمال للقبعات الصلبة أو الضوضاء التي وصلت إلى مستويات خطيرة. في البيع بالتجزئة ، يمكن لأجهزة إنترنت الأشياء قياس درجة حرارة التخزين البارد ، وتنبيه صاحب المتجر إذا كانت الثلاجة أو الفريزر خارج نطاق درجة الحرارة المطلوبة ، أو يمكنهم مراقبة العناصر الموجودة على الأرفف لتوجيه الموظفين لإعادة تعبئة المنتجات التي تم بيعها. تعتمد صناعة النقل أكثر فأكثر على إنترنت الأشياء لمراقبة مواقع المركبات ، وتتبع الأميال على الطريق لشحن مستخدمي الطريق ، وتتبع ساعات السائق وانقطاع الامتثال ، أو إخطار الموظفين عند اقتراب مركبة من المستودع للاستعداد للتحميل أو التفريغ.
</div>
<div dir="rtl">✅ ما هي أجهزة إنترنت الأشياء التجارية المتوفرة لديك في مدرستك أو مكان عملك؟ </div>
</br>
### <div dir="rtl">انترنت الأشياء الصناعي </div>
<div dir="rtl">
إنترنت الأشياء الصناعي ، أو IIoT ، هو استخدام أجهزة إنترنت الأشياء للتحكم في الآلات وإدارتها على نطاق واسع. يغطي هذا مجموعة واسعة من حالات الاستخدام ، من المصانع إلى الزراعة الرقمية.
تستخدم المصانع أجهزة إنترنت الأشياء بعدة طرق مختلفة. يمكن مراقبة الماكينات بأجهزة استشعار متعددة لتتبع أشياء مثل درجة الحرارة والاهتزاز وسرعة الدوران. يمكن بعد ذلك مراقبة هذه البيانات للسماح للجهاز بالتوقف إذا خرج عن تفاوتات معينة - يعمل على درجة حرارة عالية جدًا ويتم إيقاف تشغيله على سبيل المثال. يمكن أيضًا جمع هذه البيانات وتحليلها بمرور الوقت لإجراء الصيانة التنبؤية ، حيث ستنظر نماذج الذكاء الاصطناعي في البيانات المؤدية إلى الفشل ، وتستخدم ذلك للتنبؤ بحالات الفشل الأخرى قبل حدوثها.
تعتبر الزراعة الرقمية مهمة إذا كان كوكب الأرض يريد إطعام العدد المتزايد من السكان ، خاصة بالنسبة لملياري شخص في 500 مليون أسرة تعيش على <a href="https://wikipedia.org/wiki/Subsistence_agriculture">زراعة الكفاف</a> يمكن أن تتراوح الزراعة الرقمية من عدد قليل من أجهزة الاستشعار بالدولار الواحد ، إلى الأجهزة التجارية الضخمة. يمكن للمزارع أن يبدأ بمراقبة درجات الحرارة واستخدام <a href="https://wikipedia.org/wiki/Growing_degree-day">أيام الدرجات المتزايدة</a> للتنبؤ بموعد جاهزية المحصول للحصاد. يمكنهم ربط مراقبة رطوبة التربة بأنظمة الري الآلية لمنح نباتاتهم القدر المطلوب من المياه ، ولكن ليس أكثر لضمان عدم جفاف محاصيلهم دون إهدار المياه. بل إن المزارعين يأخذون الأمر إلى أبعد من ذلك ويستخدمون الطائرات بدون طيار وبيانات الأقمار الصناعية والذكاء الاصطناعي لمراقبة نمو المحاصيل والأمراض وجودة التربة في مساحات شاسعة من الأراضي الزراعية
</div>
<div dir="rtl">✅ ما هي أجهزة إنترنت الأشياء الأخرى التي يمكن أن تساعد المزارعين؟ </div>
### <div dir="rtl"> انترنت الاشياء البنية التحتية </div>
<div dir="rtl"> يقوم إنترنت الأشياء للبنية التحتية بمراقبة والتحكم في البنية التحتية المحلية والعالمية التي يستخدمها الناس كل يوم. </div>
<div dir="rtl"> <a href="https://wikipedia.org/wiki/Growing_degree-day">المدن الذكية </a> هي مناطق حضرية تستخدم أجهزة إنترنت الأشياء لجمع البيانات حول المدينة واستخدامها لتحسين كيفية إدارة المدينة. عادة ما يتم تشغيل هذه المدن بالتعاون بين الحكومات المحلية والأوساط الأكاديمية والشركات المحلية ، وتتبع وإدارة الأشياء التي تختلف من النقل إلى وقوف السيارات والتلوث. على سبيل المثال ، في كوبنهاغن ، الدنمارك ، يعد تلوث الهواء مهمًا للسكان المحليين ، لذلك يتم قياسه واستخدام البيانات لتوفير معلومات حول أنظف طرق ركوب الدراجات والركض. </div>
<div dir="rtl"> <a href="https://wikipedia.org/wiki/Smart_grid">شبكات الكهرباء الذكية </a> تسمح بتحليلات أفضل للطلب على الطاقة من خلال جمع بيانات الاستخدام على مستوى المنازل الفردية. يمكن أن توجه هذه البيانات القرارات على مستوى الدولة بما في ذلك مكان بناء محطات طاقة جديدة ، وعلى المستوى الشخصي من خلال إعطاء المستخدمين رؤى حول مقدار الطاقة التي يستخدمونها ، وأوقات استخدامها ، وحتى اقتراحات حول كيفية تقليل التكاليف ، مثل لشحن السيارات الكهربائية في الليل. </div>
<div dir="rtl">✅ إذا كان بإمكانك إضافة أجهزة إنترنت الأشياء لقياس أي شيء تعيش فيه ، فماذا سيكون؟</div>
</br>
### <div dir="rtl">أمثلة على أجهزة إنترنت الأشياء التي قد تكون موجودة حولك </div>
<div dir="rtl">
ستندهش من عدد أجهزة إنترنت الأشياء الموجودة حولك. أكتب هذا من المنزل و لدي الأجهزة التالية متصلة بالإنترنت بميزات ذكية مثل التحكم في التطبيق أو التحكم الصوتي أو القدرة على إرسال البيانات إلي عبر هاتفي:
* مكبرات صوت ذكية متعددة
* ثلاجة وغسالة صحون وفرن وميكروويف
* مرقاب كهرباء الألواح الشمسية
* المقابس الذكية
* جرس باب بالفيديو وكاميرات مراقبة
* ترموستات ذكي مع عدة مستشعرات ذكية للغرفة
* فتحت باب المرآب
* أنظمة الترفيه المنزلي وأجهزة التلفزيون ذات التحكم الصوتي
* أضواء
* أجهزة تتبع اللياقة البدنية والصحة
كل هذه الأنواع من الأجهزة لها مستشعرات و / أو مشغلات وتتحدث إلى الإنترنت. يمكنني معرفة ما إذا كان باب الكاراج الخاص بي مفتوحًا من هاتفي ، وأطلب من السماعة الذكية إغلاقها من أجلي. يمكنني حتى ضبطه على مؤقت ، لذلك إذا كان لا يزال مفتوحًا في الليل ، فسيتم إغلاقه تلقائيًا. عندما يرن جرس الباب ، يمكنني أن أرى من هاتفي من يوجد أينما كنت في العالم ، وأتحدث إليهم عبر مكبر صوت وميكروفون مدمجين في جرس الباب. يمكنني مراقبة الجلوكوز في الدم ومعدل ضربات القلب وأنماط النوم ، والبحث عن أنماط في البيانات لتحسين صحتي. يمكنني التحكم في الأضواء الخاصة بي عبر السحابة ، والجلوس في الظلام عندما ينقطع الاتصال بالإنترنت.
</div>
---
## <div dir="rtl">تحدي </div>
<div dir="rtl">ضع قائمة بأكبر عدد ممكن من أجهزة إنترنت الأشياء الموجودة في منزلك أو مدرستك أو مكان عملك - قد يكون هناك أكثر مما تعتقد! </div>
</br>
## <div dir="rtl">مسابقة ما بعد المحاضرة </div>
<div dir="rtl">
<a href="https://brave-island-0b7c7f50f.azurestaticapps.net/quiz/2">مسابقة ما بعد المحاضرة </a> </div>
</br>
## <div dir="rtl">المراجعة والدراسة الذاتية </div>
<div dir="rtl"> اقرأ عن مزايا وإخفاقات مشروعات إنترنت الأشياء للمستهلكين. تحقق من المواقع الإخبارية بحثًا عن مقالات عن الأوقات التي حدث فيها خطأ ، مثل مشكلات الخصوصية أو مشكلات الأجهزة أو المشكلات الناجمة عن نقص الاتصال.
بعض الأمثلة:
* قم بالاطلاع على حساب التويتر لأمثلة جيدة على انترنت الاشياء المستهلك **[Internet of Sh*t](https://twitter.com/internetofshit)** *(profanity warning)*
* [c|net - My Apple Watch saved my life: 5 people share their stories](https://www.cnet.com/news/apple-watch-lifesaving-health-features-read-5-peoples-stories/)
* [c|net - ADT technician pleads guilty to spying on customer camera feeds for years](https://www.cnet.com/news/adt-home-security-technician-pleads-guilty-to-spying-on-customer-camera-feeds-for-years/) *(trigger warning - non-consensual voyeurism)*
### الواجب
[التحقيق في مشروع إنترنت الأشياء](assignment.ar.md)
</div>

@ -0,0 +1,222 @@
# 物联网IoT简介
![这个课程概述的涂鸦笔记sketchnote](../../../sketchnotes/lesson-1.png)
> Sketchnote by [Nitya Narasimhan](https://github.com/nitya). 如果你想看比较大的图片,请点击它。
## 知识检查(初)
[知识检查(初)](https://brave-island-0b7c7f50f.azurestaticapps.net/quiz/1)
## 简介
本课程涵盖一些介绍物联网IoT的主题以及教你怎么开始设置你的硬件。
本课程将涵盖:
* [什么是 物联网IoT](#what-is-the-internet-of-things)
* [IoT 设备](#iot-devices)
* [设置你的设备](#set-up-your-device)
* [IoT 的应用场景](#applications-of-iot)
* [在你的周围的IoT 设备例子](#examples-of-iot-devices-you-may-have-around-you)
## 什么是 物联网IoT
为了形容运用感应器来链接网络与物质世界1999年 [凯文·阿什顿Kevin Ashton](https://wikipedia.org/wiki/Kevin_Ashton) 生造了物联网IoT这个词。自从那时起这个生造词被用来形容任何能够跟周围的世界交互的设备。这些设备可以使用感应器收集数据或者使用执行器会做事—例如打开开关、发光二极管等—的设备在物质世界完成任务。通常执行器会连接到其它设备或者网络。
> **感应器** 从世界中收集数据,例如:速度、温度或地点。
>
> **执行器** 将电信号转换成行动,例如:打开灯,发出声音或将控制信号传送到其它硬件。
IoT 不仅是设备,还包含云服务;这些服务能处理数据,或者将请求传送给跟 IoT 设备有链接的执行器。它也包括没有链接的设备它们通常被称为“边缘设备”而且它们有能力用基于云的AI模型自己处理与回应感应器的数据。
IoT 是一个快速发展的技术领域。专家预计2020底世界上有三百亿 IoT 设备跟网络有链接。专家也预计2025年IoT 设备将来收集大概80 ZB80万亿GB。那是个非常大的数量
![这个图表展示随着时间的推移的有源 IoT 设备它展示出一个上升趋势从2015年不超过50亿到2025年超过300亿](../../../images/connected-iot-devices.svg)
✅ 做一点儿研究: IoT 设备收集的数据,多少是有用的、多少是被浪费的?为什么那么多数据被忽略了?
对于 IoT 的成功,这些数据是不可或缺的。想成为一名有成就的 IoT 开发者,就必须了解你需要收集的数据、怎么收集它,怎么利用它来作出决定以及如果有必要的话,怎么用那些决定来跟物质世界交互。
## IoT 设备
IoT 的 **T** 代表 **Things**(物)—— 可以跟物质世界交互的设备;它们使用感应器收集数据或者使用执行器在物质世界完成任务。
为生产或商业的设备(例:健身追踪器、机器控制器等)通常是自定义生成的。它们利用的自定义生成电路板——有时连自定义生成处理器都有——设计使它们能够满足某某任务的需求。例:要戴在手上的需要够小,或者要承受高温度、高压力、高振动的工厂环境的需要够耐用。
无论你正在学 IoT 或者在创立原型设备,作为一名 IoT 开发者,你必须由一个开发者套件开始。这些是为 IoT 开发者设计的通用设备,而它们通常不会有生产设备的特点,例如用来链接感应器和执行器的外部引脚、帮助排除错误的硬件或者将生产运行中加不必要的成本的额外资源。
这些开发者套件通常有两种:微控制器和单板机。我们会在这儿介绍它们,而将在下一课更详细地解释它们。
> 💁 你的手机也算是一个通用 IoT 设备;它拥有感应器与执行器,以及有不同应用程序用不同的方式来跟不同云服务利用它们。你甚至可以找到几个用手机的应用程序当作 IoT 设备的 IoT 教程。
### 微控制器
一个微控制器MCU是一个小电脑。它包含
🧠 至少一个中央处理器CPU它就是微控制器的“脑”——运行你的程序
💾 内存随机存取存储器RAM和程序存储器——储存你的程序、数据变量的地方
🔌 可编程输入输出I/O连接——为了跟外围设备如感应器或执行器沟通
微控制器通常是较便宜的计算设备;自定义生成硬件的平均成本下降到 US$0.50,而也有些设备到 US$0.03 那么便宜。开发者套件的价钱可以从 US$4 起,但你加上越多特点,价钱就越高。[Wio Terminal](https://www.seeedstudio.com/Wio-Terminal-p-4509.html) 是个来自 [Seeed studios](https://www.seeedstudio.com) 的微控制器它包含感应器、执行器、Wi-Fi和一个屏幕总共算起来大约 US$30。
![一个Wio Terminal](../../../images/wio-terminal.png)
> 💁 当你在网上寻找微控制器时,要小心用 **MCU** 这个词因为这回带来许多关于漫威电影宇宙Marvel Cinematic Universe的搜索结果而不是关于微控制器的。
微控制器的设计允许它们被编程完成几个非常特定的任务,不像比较通用的电脑。除了一些很具体的情况,你无法连接显示器、键盘和鼠标并利用它完成通用任务。
微控制器开发者套件平时包括额外的感应器和执行器。大多数的会有至少一个能被编程的发光二极管LEDs还有其它设备如普通插头用来链接更多应用其或执行器或内置感应器平时最常见的如温度。有些微控制器有内置的无线连接如蓝牙或 Wi-Fi或者有额外微控制器用来加这个连接性能。
> 💁 我们通常用 C 或 C++ 来为微控制器写程序。
### 单板机
单板机指的是一个小计算器;它把一个电脑的所有要素装在单单一个小板上。这些设备的规格跟台式电脑或笔记本电脑比较相似,它们也运行完整的操作系统,但它们较小,用比较少电力以及便宜多了。
![一个 Raspberry Pi 4](../../../images/raspberry-pi-4.jpg)
***Raspberry Pi 4. Michael Henzler / [Wikimedia Commons](https://commons.wikimedia.org/wiki/Main_Page) / [CC BY-SA 4.0](https://creativecommons.org/licenses/by-sa/4.0/)***
Raspberry Pi 是其中最流行的单板机。
就像一个微控制器,单板机有个中央处理器、内存和输入输出引脚,但它们也有额外的特点如一个让你链接显示器的图形芯片、音频输出与 USB 端口让你链接键盘、鼠标和其它普通 USB 设备如网络摄像头和外置储存。程序将在 SD 卡或硬盘以及一个操作系统被储存,而不是通过一个内置的存储芯片。
> 🎓 你可以把单板机当成一个较小、较便宜的电脑版本,就像你现在正在用来读这些的电脑。可是,单板机还加了通用输入/输出端口,让你和感应器、执行器交互。
单板机有电脑的所有要素,所以你可以用任何编程语言来为它写程序。我们通常用 Python 为 IoT 设备写程序。
### 为其余的课的硬件选择
其余的课程都包括作业,而且你必须用一个 IoT 设备跟物质世界交互以及跟云沟通。每个课程会支持3种设备选择Arduino通过一个 Seeed Studios Wio Terminal或者一个单板机——一个物质设备一个 Raspberry Pi 4 或一个在你的电脑上运行的虚拟单板机。
你能在[硬件手册](../../../hardware.md)查到需要用来完成作业的硬件。
> 💁 你不需要为了完成作业而买任何 IoT 硬件;所有东西可以使用一个虚拟单板机来做。
要使用哪个硬件是你的选择,取决于你家里或学校里有什么,以及你知道或想学的编程语言。两种硬件都利用同样的感应器系统,所以万一你想途中改变你的选择,你也不需要替换大部分的套件。用虚拟单板机学跟用一个 Raspberry Pi 学差不多一模一样,而且你可以把大多数的程序转换去你的 Pi 如果你后来得到一个设备和感应器。
### Arduino 开发者套件
如果你对微控制器的开发感兴趣,那你可以用一个 Arduino 设备完成作业。你需要对 C 或 C++ 的编程语言有基本的理解,因为将来的课程只会教关于 Arduino 框架的程序、需要用到的感应器和执行器以及跟云交互的库。
作业将用 [Visual Studio Code](https://code.visualstudio.com/?WT.mc_id=academic-17441-jabenn) 跟 [为微控制器开发的 PlatformIO 扩展](https://platformio.org). 如果你对 Arduino IDE 熟悉的话,你也能用它,但我们不会提供指示。
### 单板机开发者套件
如果你对使用单板机学 IoT 开发有兴趣,你可以用一个 Raspberry Pi 完成作业,或者在你的电脑运行的虚拟设备。
你需要对 Python 有基本的理解,因为将来的课程只会教关于需要用到的感应器和执行器的程序以及跟云交互的库。
> 💁 如果你想学怎么用 Python 写程序,看一看一下的两个视频系列:
>
> * [Python for beginners为初学者的 Python](https://channel9.msdn.com/Series/Intro-to-Python-Development?WT.mc_id=academic-17441-jabenn)
> * [More Python for beginners更多为初学者的 Python](https://channel9.msdn.com/Series/More-Python-for-Beginners?WT.mc_id=academic-7372-jabenn)
作业将用 [Visual Studio Code](https://code.visualstudio.com/?WT.mc_id=academic-17441-jabenn)。
如果你在用一个 Raspberry Pi为了运行你的 Pi你可以通过完整的桌面 Raspberry Pi 操作系统以及用 [VS Code 的 Raspberry Pi 操作系统版本](https://code.visualstudio.com/docs/setup/raspberry-pi?WT.mc_id=academic-17441-jabenn)直接在你的 Pi 写程序,或者把它当成一个无头设备,从你的电脑用 VS Code 的 [Remote SSH 扩展](https://code.visualstudio.com/docs/remote/ssh?WT.mc_id=academic-17441-jabenn)写程序;这个扩展让你链接你的 Pi便编辑你的程序、从程序排除错误和运行程序就像如果你直接在 Pi上写程序一样。
如果你选择用虚拟设备,你会直接在你的电脑上写程序。你不会读取感应器和执行器,反而你会用模拟工具来定义传感器值以及在屏幕上查看执行器的结果。
##设置你的设备
在你为你的 IoT 设备写程序前,你需要做点设置。请根据你将用到的设备,按照以下的指示。
> 💁 如果你还缺少了一个设备,请用[硬件手册](../../../hardware.md) 帮你决定你要用的是哪个设备,以及你需要买的额外硬件。你不必买硬件,因为你可以用虚拟硬件运行所有的项目。
这些指示包括第三方网站的链接;这些网站由你将用到的硬件或工具的创造者。这是为了确保你会一直在按照各种工具和硬件的最新指示。
按照相当的指南来设置你的设备并完成一个“Hello World”项目。我们将在这个介绍部分用4个课程创造一个 IoT 夜灯,而这是第一步。
* [ArduinoWio Terminal](wio-terminal.md)
* [单板机Raspberry Pi](pi.md)
* [单板机:虚拟设备](virtual-device.md)
## IoT 的应用场景
IoT 有好多用例,跨过几组:
* 消费者 IoT
* 商业 IoT
* 工业 IoT
* 基础设施 IoT
✅ 做一点儿研究:关于以下的每个范围,找一下一个不在内容里的详细例子。
###消费者 IoT
消费者 IoT 指的是消费者将买以及在家里用的 IoT 设备。这些设备中有的非常有用,例如:智能音箱、智能供暖和机器人吸尘器。其它的有些用例比较可疑,好像声控水龙头;你无法把它们关掉因为有了流水的声音,声控就无法听到你的语音。
消费者 IoT 设备使人能够在他们的周围做成更多东西尤其是世界上的10亿个残障人士。机器人吸尘器能为移动有困难、无法自己清扫的人提供干净的地板、声控烤箱让视力或移动力较差的人用自己的语音来给烤箱加热、健康监测器使患者能够自己监测自己的慢性病情况并定期得到更加详细的信息。这些设备将变得普及到连小孩子也在天天用着它们如学生们在冠状病毒疫情时进行居家学习、利用智能家居设备的计时器来记录他们的功课或者设置闹钟来提醒他们参与他们未来的课程。
✅ 你人身上或家里有什么消费者 IoT 设备呢?
### 商业 IoT
商业 IoT 包含公司里的 IoT 用例。在办公室里有可能会有空间占用传感器和移动探测器被用来管理灯光和供暖以及在不需要的时候把它们关掉以避免浪费钱和减少碳排放。在个工厂IoT 设备可以监测安全隐患例如没有戴安全帽的人员或过于大的巨响。在店里IoT 设备可以量冷库的温度,并通知店主如果某个冰箱的温度超过理想范围,或者它们可以监测架子上的产品,并通知工作人员如果他们为买完的产品补货。交通运输业也越来越依靠 IoT 设备来监测交通工具的地点、为道路使用者收费记录行驶里程、记录司机的工作时间和徐熙时间或者通知工作人员如果有货车即将来到仓库,并为上货或下货做准备。
✅ 你的学校或公司里有什么消费者 IoT 设备呢?
### 工业 IoT (IIoT)
工业 IoT也称为 “IIoT”指的是使用 IoT 设备在大范围上来控制与管理机械。这包含很多用例,从工厂到数字农业。
IoT 设备在工厂中有很多用例。它们能使用各种感应器温度、振动、旋转速度等来监测机械。我们将可以观察这些数据而如果机器超出某些公差如它的温度太高我们可以把它停下来。我们也能收集并分析这些数据让人工智能AI模型看故障前的数据再利用它预报其它未来的故障这就叫做“预测性维护”。
为了养活不断增长的人口,数字农业非要不可,尤其是对于依靠[自给农业](https://wikipedia.org/wiki/Subsistence_agriculture) 的5亿家户中的20亿人。数字农业的范围包含才几块钱的感应器也包含大大的初创企业。首先一位农民可以监测温度以及用[生长度日GDD](https://wikipedia.org/wiki/Growing_degree-day),预测农作物能什么时候收割。再次,为了确保植物有充足的水量和避免浪费太多水,他们可以连接土壤水分监测。最后,农民可以进一步、用无人驾驶飞机、卫星数据、人工智能来监测大面积农田的作物生长、疾病和土壤质量。
✅ 还有什么 IoT 设备可以用来帮助农民呢?
### 基础设施 IoT
基础设施 IoT 指的是监测与控制民众天天用的本地与全球基础设施。
[智慧城市](https://wikipedia.org/wiki/Smart_city)是用 IoT 设备来收集关于城市的数据再利用它们来改善城市运行方式的城市地区。这些城市通常靠本地政府、学术界和本地企业之间的合作,监测和管理各种东西——从交通到污染。一个例子是在哥本哈根(丹麦王国首都),空气污染对人民来说非常重要,所以城市量它,再用它给人民提供关于最环保的骑自行车路线与步道的信息。
[智能电网](https://wikipedia.org/wiki/Smart_grid)以收集各各家户使用电力的数据的方式来允许更好的电力需求分析。这些数据能影响国家的某些决定,包括在哪里建新发电厂。它们也能影响我们的个人决定;它们让我们明确地了解我们使用多少电力、我们在什么时候使用电力,还可以为我们提供减少浪费的意见,例如晚上为电动汽车充电。
✅ 假如你可以在你住的地方加 IoT 设备来量任何东西,那会是什么?
##在你的周围的 IoT 设备例子
你会惊讶于你身边有多少 IoT 设备。我正在家里写这个课程的内容,而却在我的周围通过智能特点(应用程式控制、语音控制、通过手机把数据寄给我的能力)跟互联网有连接有以下的设备:
* 好几个智能音箱
* 冰箱、洗碗机、烤箱和微波炉
* 为太阳能电池板的电量监测器
* 智能插座
* 摄像门铃和监视器
* 有好几个在房间里的智能传感器的智能恒温器
* 车库开门器
* 家庭娱乐系统和声控电视
* 灯光
* 健身和健康追踪器
这些设备都有感应器和/或执行器与跟互联网沟通。从我的手机,我能看得出如果我的车库门还开着,再叫我的智能音箱替我把它关上。我甚至能用计时器,那万一它晚上还开着,它可以自动关上。每当我的门铃响着,无论我在世界的哪儿个地方,我都能从手机看到门前是谁,并通过门铃的音箱和麦克风跟他们沟通。我能监测我的血糖、心率和睡眠周期,再用数据中的趋势来改善自己的健康状况。我能通过云控制我的灯,而当我的网络连接出状况,我能在黑暗中坐着。
---
## 🚀 挑战
将在你的家、学校或工作场所中的 IoT 设备列成单子——有可能比你的想象中还要多!
##知识检查(后)
[知识检查(后)](https://brave-island-0b7c7f50f.azurestaticapps.net/quiz/2)
## 复习和自学
读一下关于消费者 IoT 项目的成功和失败。在新闻网站上找一找关于失败的文章,例如:隐私问题、硬件问题或者因缺少连接性能而发生的问题。
几个例子:
* 这个推特户口 **[Internet of Sh*t](https://twitter.com/internetofshit)** *(亵渎警告)* 有几个关于消费者 IoT 失败的好例子。
* [c|net - My Apple Watch saved my life: 5 people share their stories](https://www.cnet.com/news/apple-watch-lifesaving-health-features-read-5-peoples-stories/)
* [c|net - ADT technician pleads guilty to spying on customer camera feeds for years](https://www.cnet.com/news/adt-home-security-technician-pleads-guilty-to-spying-on-customer-camera-feeds-for-years/) *(触发警告:未经同意的偷窥)*
## 作业
[调查一个物联网IoT项目](assignment.md)

@ -0,0 +1,20 @@
<div dir="rtl">
# التحقيق في مشروع إنترنت الأشياء
## تعليمات
هناك العديد من مشاريع إنترنت الأشياء الكبيرة والصغيرة التي يتم طرحها على مستوى العالم ، من المزارع الذكية إلى المدن الذكية ، ومراقبة الرعاية الصحية ، والنقل ، أو استخدام الأماكن العامة.
ابحث في الويب عن تفاصيل المشروع الذي يثير اهتمامك ، ومن الأفضل أن يكون مشروعًا قريبًا من المكان الذي تعيش فيه. اشرح الجوانب الإيجابية والسلبية للمشروع ، مثل الفائدة التي تأتي منه ، وأي مشاكل يسببها وكيف يتم أخذ الخصوصية في الاعتبار.
## الموضوع
| المعايير | نموذجي | كافية | يحتاج إلى تحسين |
| -------- | --------- | -------- | ----------------- |
| اشرح الإيجابيات والسلبيات | قدّم شرحاً واضحاً لأوجه الإيجابيات والسلبيات للمشروع | قدم شرحا مختصرا للجوانب الإيجابية والسلبية | لم يشرح الإيجابيات أو السلبيات |
</div>

@ -0,0 +1,13 @@
# একটি IoT প্রজেক্ট পর্যালোচনা
## নির্দেশাবলী
স্মার্ট ফার্ম থেকে শুরু করে স্মার্ট শহরগুলিতে, স্বাস্থ্যসেবা পর্যবেক্ষণ, পরিবহন এবং জনসাধারণের ব্যবহারের জন্য বিশ্বব্যাপী বড় এবং ছোট আকারের অনেক আইওটি প্রকল্প আসছে।
আপনার বসবাসের জায়গার আশেপাশের এমন কোন প্রকল্প থাকলে, সেটি সম্পর্কে ইন্টারনেটে সার্চ করুন। প্রজেক্টটির ইতিবাচক এবং নেতিবাচক দিকগুলো (যেমন: এটির কারণে কী কী সুবিধা হচ্ছে, কোন সমস্যা তৈরী করছে কিনা বা তথ্যের গোপনীয়তা সংক্রান্ত বিষয়গুলি কীভাবে দেখা হচ্ছে) ব্যখ্যা করুন।
## এসাইনমেন্ট মূল্যায়ন মানদন্ড
| ক্রাইটেরিয়া | দৃষ্টান্তমূলক ব্যখ্যা | পর্যাপ্ত ব্যখ্যা | আরো উন্নতির প্রয়োজন |
| -------- | --------- | -------- | -----------------|
| ইতিবাচক এবং নেতিবাচক দিকগুলোর ব্যখ্যা করুন | বিশদভাব ব্যখ্যা করা হয়েছে | সংক্ষিপ্ত ব্যখ্যা করা হয়েছে | ভালোভাবে ব্যখ্যা করা হয়নি |

@ -0,0 +1,13 @@
# 调查一个物联网IoT项目
## 指示
从智慧农场到智慧城市、医疗保健监测系统、交通或利用公共空间等世界上有非常多IoT项目。
在互联网寻找一个让你感兴趣的IoT项目的细节最好是离你不太远的。解释一下项目的好处与坏处例如它带来的益处、它带来的任何麻烦以及他怎么顾及隐私。
## 评分表
| 条件 | 优秀 | 一般 | 需改进 |
| -------- | --------- | -------- | ----------------- |
| 解释项目的好处与坏处 | 把项目的好处与坏处解释得很清楚 |简要地解释项目的好处与坏处 | 没有解释项目的好处与坏处 |

@ -0,0 +1,244 @@
# রাস্পবেরি পাই
[রাস্পবেরি পাই](https://raspberrypi.org) হলো একটি সিংগেল বোর্ড কম্পিউটার । আমরা বিভিন্ন ইকোসিস্টেমের সেন্সর এবং অ্যাকচুয়েটর ব্যবহার করতে পারি, আর এই লেসনে আমরা [Grove](https://www.seeedstudio.com/category/Grove-c-1003.html) নামের বেশ সমৃদ্ধ একটি হার্ডওয়্যার ইকোসিস্টেম ব্যবহার করবো। আমাদের রাস্পবেরি পাই (সংক্ষেপে "পাই") এর কোডিং এবং Grove সেন্সরগুলো আমরা নিয়ন্ত্রণ করবো পাইথন ল্যাংগুয়েজে।
![A Raspberry Pi 4](../../../images/raspberry-pi-4.jpg)
***রাস্পবেরি পাই - Michael Henzler / [Wikimedia Commons](https://commons.wikimedia.org/wiki/Main_Page) / [CC BY-SA 4.0](https://creativecommons.org/licenses/by-sa/4.0/)***
## সেটাপ
যদি আমরা আমাদের আইওটি হার্ডওয়্যার হিসাবে রাস্পবেরি পাই ব্যবহার করি, তবে দুটি অপশন আছে - সবগুলো লেসন পড়ে সরাসরি রাসপবেরি পাই তে কোডের মাধ্যমে কাজ করা অথবা কম্পিউটার থেকে 'হেডলেস' পাই এবং কোডের সাথে দূরবর্তীভাবে সংযোগ করতে পারেন।
কাজ শুরু করার আগে আমাদের গ্রোভ বেস হ্যাটটি আপনার পাইয়ের সাথে সংযুক্ত করতে হবে।
### কাজ - সেটাপ
Grove বেস হ্যাটটি রাস্পবেরি পাই এ ইন্সটল করা এবং পাই কে সেই অনুসারে কনফিগার করা।
১. গ্রোভ বেস টুপিটি রাস্পবেরি পাই এর সাথে সংযুক্ত করতে হবে। নিচের ছবির মতো, জিপিআইও পিনগুলো বরাবর আমরা গ্রোভ হ্যাট বসাতে পারবো।
![Fitting the grove hat](../../../images/pi-grove-hat-fitting.gif)
২. কীভাবে রাস্পবেরি পাই তে কাজ করতে চাচ্ছি, সে সম্পর্কিত সিদ্ধান্ত নিয়ে - নিচের যেকোন একটি প্রাসঙ্গিক সেকশন এ যেতে হবে
* [সরাসরি রাস্পবেরি পাই তে কাজ করা](#সরাসরি-রাস্পবেরি-পাই-তে-কাজ-করা)
* [রাস্পবেরি পাই তে রিমোট একসেস নেয়া](#পাই-তে-রিমোট-একসেস)
### সরাসরি রাস্পবেরি পাই তে কাজ করা
আমরা যদি সরাসরি রাস্পবেরি পাই তে কাজ করতে চাই, সেক্ষত্রে আমাদেরকে Raspberry Pi OS এর ডেস্কটপ ভার্সন ব্যবহার করতে হবে এবং প্রয়োজনীয় সব উপাদান ইন্সটল করতে হবে।
#### কাজ - সরাসরি রাস্পবেরি পাই
আমাদেরকে রাস্পবেরি পাই সেটাপ করে নিতে হবে।
1. [ রাস্পবেরি পাই সেটাপ গাইড](https://projects.raspberrypi.org/en/projects/raspberry-pi-setting-up) থেকে সব নির্দেশ অনুসরণ করে আমাদের পাই সেটাপ করে নিতে হবে। এটিকে এবার কীবোর্ড/মাউস/মনিটরের সাথে যুক্ত করি। তারপর ওয়াইফাই বা ইথারনেটে সংযুক্ত করে, সফটওয়্যর আপডেট করে নিতে হবে। এক্ষেত্রে যে অপারেটিং সিস্টেম আমরা ডাউনলোড করবো তা হলো **Raspberry Pi OS (32 bit)** , এটিই রেকমেন্ডেড হিসেবে মার্ক করা থাকে ।
গ্রোভ সেন্সর ও একচুয়েটর ব্যবহার করে কাজ করার জন্য, আগেই একটি এডিটর ইন্সটল করতে হবে যাতে আমরা কোড লিখতে পারি এবং বিভিন্ন লাইব্রেরি ও ট্যুল ব্যবহার করতে পারি - এতে করে সহজেই আমরা গ্রোভে কাজ করতে পারবো।
1. পাই রিব্যুট করার পরে, উপরের মেন্যু বার থেকে **Terminal** আইকনে ক্লিক করে তা চালু করতে হবে অথবা *Menu -> Accessories -> Terminal* এভাবে চালু করতে হবে।
2. ওএস এবং সব সফটওয়্যর আপডেট করা আছে কিনা তার জন্য নীচের কমান্ড টা রান করতে হবে।
```sh
sudo apt update && sudo apt full-upgrade --yes
```
3. গ্রোভে সকল লাইব্রেরি ইন্সটল করার জন্য নিচের কমান্ড রান দিই।
```sh
curl -sL https://github.com/Seeed-Studio/grove.py/raw/master/install.sh | sudo bash -s -
```
পাইথনের অন্যতম শক্তিশালী একটি সুবিধা হলো [pip packages](https://pypi.org) ইন্সটল করতে পারা - পিপ প্যাকেজ হলো অন্যদের তৈরী ও পাবলিশ করা কোডের প্যাকেজ। মাত্র ১টা কমান্ড দিয়েই পিপ ইন্সটল করে ব্যবহার করা যায়। এই গ্রুভ ইন্সটল স্ক্রিপ্ট টি রান করলে, তা আমাদের প্রয়োজনীয় সকল ট্যুল ইন্সটল করে নিবে।
4. আমাদের রাস্পবেরি পাই টি মেন্যু থেকে অথবা নিচের স্ক্রিপ্ট রান করে রিব্যুট করে নিই।
```sh
sudo reboot
```
5. পাই রিব্যুট হওয়ার পর, টার্মিনাল আবারো চালু করতে হবে আর [Visual Studio Code (VS Code)](https://code.visualstudio.com?WT.mc_id=academic-17441-jabenn) ইন্সটল করতে হবে। এই এডিটরের সাহায্যেই মূলত আমরা সব কোড লিখবো।
```sh
sudo apt install code
```
ইন্সটলেশনের পর টপ মেন্যু থেকেই ভিএস কোড পাওয়া যাবে।
> 💁 পছন্দানুসারে যেকোন পাইথন আইডিই বা এডিটর ব্যবহার করলেই হয়, কিন্তু আমরা এখানে সম্পূর্ণ টিউটোরিয়াল সাজিয়েছি ভিএস কোডের উপর ভিত্তি করে।
6. Pylance ইন্সটল করতে হবে। পাইথনে কোড করার জন্য, এটি ভিএস কোডের একটি এক্সটেনশন। [Pylance extension documentation](https://marketplace.visualstudio.com/items?itemName=ms-python.vscode-pylance&WT.mc_id=academic-17441-jabenn) থেকে এটি ইন্সটল করার সকল নির্দেশনা পাওয়া যাবে।
### পাই তে রিমোট একসেস
কম্পিউটারের কীবোর্ড/মাউস/মনিটরের সাথে যুক্ত না রেখে, সরাসরি এটিতে কোডিং না করে, আমরা 'হেডলেস' হিসেবে এটাকে রান করতে পারি। এক্ষেত্রেও ভিস্যুয়াল স্টুডিও কোড ব্যবহার করে আমরা কনফিগারেশন এবং কোডিং করবো।
#### পাই অপারেটিং সিস্টেম সেটাপ করা
পাই ওএস কে একটি এসডি কার্ডে ইন্সটল করে রাখতে হবে।
##### কাজ- পাই ওএস সেটাপ
হেডলেস পাই ওএস সেটাপ করা :
1. [Raspberry Pi OS software page](https://www.raspberrypi.org/software/) থেকে **Raspberry Pi Imager** ডাউনলোড এবং ইন্সটল করতে হবে।
1. কম্পিউটারে একটি এসডি কার্ড প্রবেশ করাতে হবে (এডাপটার প্রয়োজন হতে পারে) ।
1. রাস্পবেরি পাই ইমেজার চালু করতে হবে ।
1. রাস্পবেরি পাই ইমেজার থেকে **CHOOSE OS** সিলেক্ট করি। তারপর *Raspberry Pi OS (Other)* সিলেক্ট করতে হবে *Raspberry Pi OS Lite (32-bit)* এর পরে ।
![The Raspberry Pi Imager with Raspberry Pi OS Lite selected](../../../images/raspberry-pi-imager.png)
> 💁 Raspberry Pi OS Lite হলো মূলত Raspberry Pi OS এরই একটি ভার্সন যার ডেস্কটপ ইন্টারফেস বা এই সংক্রান্ত ট্যুল নেই। হেডলেস পাই তে এসব দরকার নেই বলেই লাইট ভার্সন নেয়া হচ্ছে যাতে প্রক্রিয়াটি সংক্ষিপ্ত হয় এবং দ্রুত ব্যুট করা যায়।
1. **CHOOSE STORAGE** এ ক্লিক করে, এসডি কার্ড সিলেক্ট করি ।
1. **Advanced Options** চালু করতে হবে, `Ctrl+Shift+X` প্রেস করে। এখান থেকে আমরা পাই এর কিছু প্রি-কনফিগারেশন করতে পারবো।
1. এখন **Enable SSH** বক্সে টিক দিতে হবে এবং পাই ইউজারের জন্য পাসওয়ার্ড সেট করতে হবে। এই পাসওয়ার্ডটি আমরা পরে পাইতে লগ ইন করতে ব্যবহার করবো।
1. যদি আমাদেরকে পাই কে ওয়াইফাইয়ের সাথে সংযোগ স্থাপনের মাধ্যমে কাজ করার ইচ্ছে থাকে, তাহলে **Configure WiFi** চেক বাক্সটি চেক করুন এবং আমাদের ওয়াইফাই, এসএসআইডি এবং পাসওয়ার্ড লিখে, দেশ নির্বাচন করতে হবে। যদি ইথারনেট ক্যাবল ব্যবহার করি, তবে এটি করার দরকার নেই। এখানে অবশ্যই নিশ্চিত থাকতে হবে যে, পাই কে যে নেটওয়ার্কে সংযোগ করা হচ্ছে, সেই একই নেটওয়ার্কে কম্পিউটারটি যুক্ত রয়েছে।
1. **Set locale settings** বক্সে টিক দিতে হবে এব দেশ এবং টাইমজোন দিতে হবে।
1. **SAVE** সিলেক্ট করি।
1. এবার **WRITE** ক্লিক করলে ওএস আর এসডি কার্ডের কাজ শুরু। যদি ম্যাক-ওএস ব্যবহার করলে এক্ষেত্রে পাসওয়ার্ডটি প্রবেশ করতে বলা হবে যা ডিস্ক ইমেজ এ কাজ করার একসেস দেয়।
অপারেটিং সিস্টেমটি এসডি কার্ডে 'write' করা হবে এবং কার্ডটি সম্পূর্ণ হয়ে গেলে ওএস দ্বারা 'ইজেক্ট' করে দেওয়া হবে এবং ইউজারকে অবহিত করা হবে। এটি হয়ে গেলে, কম্পিউটার থেকে এসডি কার্ড সরিয়ে তা পাই তে প্রবেশ করিয়ে তা চালু করতে হবে।
#### পাই এর সাথে সংযোগ
পরবর্তী ধাপ হলো পাই তে রিমোট একসেস পাওয়া। এটি `ssh` ব্যবহার করে করা যায়, যা ম্যাক-ওএস, লিনাক্স এবং উইন্ডোজের সাম্প্রতিক ভার্সনগুলোতে রয়েছে।
##### কাজ - পাই এর সাথে সংযোগ
পাই এ রিমোট একসেস
1. টার্মিনাল বা কমান্ড প্রম্পট চালু করতে হবে এবং পাই কে যুক্ত করার জন্য নীচের কমান্ডটি চালু করতে হবে।
```sh
ssh pi@raspberrypi.local
```
উইন্ডোজের পুরাতন ভার্সন, যেসবে `ssh` নেই সেখানে কী করা যায় ? খুব সহজ - OpenSSH ব্যবহার করা যাবে। ইন্সটল করার সব নির্দেশনা [OpenSSH installation documentation](https://docs.microsoft.com//windows-server/administration/openssh/openssh_install_firstuse?WT.mc_id=academic-17441-jabenn) এ পাওয়া যাবে।
1. এটি পাইয়ের সাথে সংযুক্ত হয়ে এবং পাসওয়ার্ড চাইবে।
আমাদের কম্পিউটার নেটওয়ার্ক `<hostname>.local` এই কমান্ডের মাধ্যমে জানতে পারাটা বেশ নতুন একটি ফীচার লিনাক্স এবং উইন্ডোজে। যদি লিনাক্স বা উইন্ডোজে এইক্ষেত্রে হোস্টনেম পাওয়া না গিয়ে বরং এরর আসে তাহলে, অতিরিক্ত সফটওয়্যার ইন্সটল করতে হবে যাতে করে 'ZeroConf networking' চালু করা যায় (এপল ডিভাইসের জন্য 'Bonjour'):
1. লিনাক্স ব্যবহারকারী হলে, Avahi ইন্সটল করতে হবে নীচের কমান্ড ব্যবহার করে:
```sh
sudo apt-get install avahi-daemon
```
1. উইন্ডোজে সবচেয়ে সহজে 'ZeroConf networking' চালু করার জন্য [Bonjour Print Services for Windows](http://support.apple.com/kb/DL999) ইন্সটল করলেই হবে। এছাড়াও [iTunes for Windows](https://www.apple.com/itunes/download/) ইন্সটল করলেও হবে, আর এতে কিছু নতুন সুবিধা রয়েছে যা স্ট্যান্ড-এলোন হিসেবে সাধারণত পাওয়া যায়না।
> 💁 যদি `raspberrypi.local` ব্যবহার করে কানেক্ট করা না যায় , তখন পাই এর আইপি এড্রেস ব্যবহার করতে হবে। এই সংক্রান্ত নির্দেশনা [Raspberry Pi IP address documentation](https://www.raspberrypi.org/documentation/remote-access/ip-address.md) এ বিস্তারিত দেয়া রয়েছে।
1. রাস্পবেরি পাই ইমেজার এডভান্সড অপশনে যে পাসওয়ার্ডটি সেট করা হয়েছিল, তা প্রবেশ করাতে হবে।
#### পাই এ সফ্টওয়্যার কনফিগার
একবার পাইয়ের সাথে সংযুক্ত হয়ে গেলে, আমাদেরকে খেয়াল রাখতে হবে ওএস আপ টু ডেট রয়েছে কিনা এবং গ্রোভ হার্ডওয়ারের সাথে যুক্ত বিভিন্ন লাইব্রেরি এবং সরঞ্জাম ইনস্টল করতে হবে।
##### কাজ - পাই সফ্টওয়্যার কনফিগার
পাই সফ্টওয়্যার কনফিগার এবং গ্রোভ লাইব্রেরি ইন্সটল করা।
1. `ssh` সেশন থেকে, নিচের কমান্ডগুলো রান করতে হবে এবং আপডেট করার পর , পাই রিব্যুট করতে হবে।
```sh
sudo apt update && sudo apt full-upgrade --yes && sudo reboot
```
আপডেট এবং রিব্যুট হয়ে যাবে আর তা শেষ হলে `ssh`সেশন শেষ হয়ে যাবে। তাই ৩০ সেকেন্ড পর পুনরায় কানেক্ট করতে হবে।
1. রিকানেক্ট করা `ssh` সেশনে , নিচের কমান্ডগুলো রান করতে হবে গ্রোভ লাইব্রেরি ইন্সটল করার জন্য:
```sh
curl -sL https://github.com/Seeed-Studio/grove.py/raw/master/install.sh | sudo bash -s -
```
পাইথনের অন্যতম শক্তিশালী একটি সুবিধা হলো [pip packages](https://pypi.org) ইন্সটল করতে পারা - পিপ প্যাকেজ হলো অন্যদের তৈরী ও পাবলিশ করা কোডের প্যাকেজ। মাত্র ১টা কমান্ড দিয়েই পিপ ইন্সটল করে ব্যবহার করা যায়। এই গ্রুভ ইন্সটল স্ক্রিপ্ট টি রান করলে, তা আমাদের প্রয়োজনীয় সকল ট্যুল ইন্সটল করে নিবে।
1. নিচের কমান্ডটি রান করে রিব্যুট করতে হবে:
```sh
sudo reboot
```
পাই রিব্যুট হওয়ার পর `ssh`সেশন শেষ হয়ে যাবে। রিকানেক্ট করার আর প্রয়োজন নেই।
#### রিমোট একসেসের জন্য ভিএস কোড কনফিগার
পাই কনফিগার করার পরে, এটাতে Visual Studio Code (অর্থাৎ VS Code) এর মাধ্যমে কানেক্ট করা যাবে।
##### কাজ - রিমোট একসেসের জন্য ভিএস কোড কনফিগার
প্রয়োজনীয় সফ্টওয়্যার ইনস্টল করে এবং পাই এর সাথে রিমোট বা দূরবর্তী সংযোগ স্থাপন করতে হবে।
1. [VS Code documentation](https://code.visualstudio.com?WT.mc_id=academic-17441-jabenn) অনুসারে ভিসুয়াল স্টুডিও কোড ইন্সটল করতে হবে।
1. তারপর [VS Code Remote Development using SSH documentation](https://code.visualstudio.com/docs/remote/ssh?WT.mc_id=academic-17441-jabenn) অনুসরণ করে প্রয়োজনীয় সব কম্পোনেন্ট ইন্সটল করতে হবে।
1. একই গাইড ফলো করে রাস্পবেরি পাই কে ভিএস কোডের সাথে সংযুক্ত করতে হবে।
1. কানেক্ট হয়ে যাওয়ার পরে [managing extensions](https://code.visualstudio.com/docs/remote/ssh#_managing-extensions?WT.mc_id=academic-17441-jabenn) অনুসারে [Pylance extension](https://marketplace.visualstudio.com/items?itemName=ms-python.vscode-pylance&WT.mc_id=academic-17441-jabenn) রিমোট মাধ্যমে পাই তে ইন্সটল করতে হবে।
## Hello world (হ্যালো ওয়ার্লড)
কোন নতুন প্রোগ্রামিং ভাষা বা প্রযুক্তি শেখা শুরু করার সময় এটি প্রচলিত রয়েছে যে - একটি 'হ্যালো ওয়ার্ল্ড' অ্যাপ্লিকেশন তৈরির মাধ্যমে যাত্রা শুরু করা । 'হ্যালো ওয়ার্ল্ড'- একটি ছোট অ্যাপ্লিকেশন যা `"Hello World"` আউটপুট হিসেবে প্রদান করবে আর এতে আমরা বুঝতে পারি যে আমাদের সব কনফিগারেশন ঠিক আছে কিনা।
এক্ষেত্রে 'হ্যালো ওয়ার্ল্ড' অ্যাপটি নিশ্চিত করবে যে আমাদের পাইথন এবং ভিজ্যুয়াল স্টুডিও কোডটি সঠিকভাবে ইনস্টল করা হয়েছে।
এই অ্যাপ্লিকেশনটি `nightlight` নামে একটি ফোল্ডারে থাকবে এবং নাইটলাইট অ্যাপ্লিকেশনটি তৈরি করতে এই অ্যাসাইনমেন্টের পরবর্তী অংশগুলিতে এটি বিভিন্ন কোডের সাথে পুনরায় ব্যবহার করা হবে।
### কাজ - হ্যালো ওয়ার্লড
'হ্যালো ওয়ার্ল্ড' অ্যাপ তৈরী করা
1. ভিএস কোড চালু করতে হবে। সরসারি রাস্পবেরি পাই অথবা কম্পিউটার থেকে এটি করা যাবে যা Remote SSH extension দিয়ে পাই এর সাথে যুক্ত ।
1. ভিএস কোডের টার্মিনাল চালু করতে হবে, এজন্য আমাদেরকে এই ধারা অনুসরণ করতে হবে *Terminal -> New Terminal অথবা `` CTRL+` `` টাইপ করে। এটি `pi` ইউজারের হোম ডিরেক্টরি চালু করবে।
1. নিচের কমান্ড রান করার মাধ্যমে কোড এর জন্য একটি ডিরেক্টরি ক্রিয়েট করা হবে এবং আমরা `app.py` নামের একটি পাইথন ফাইল সেই ডিরেক্টরি তে তৈরী করছি:
```sh
mkdir nightlight
cd nightlight
touch app.py
```
1. এই ফোল্ডারটি ভিএস কোডের মাধ্যমে ওপেন করতে হবেঃ *File -> Open...* তারপর *nightlight* folder সিলেক্ট করে **OK** তে ক্লিক করতে হবে।
![The VS Code open dialog showing the nightlight folder](../../../images/vscode-open-nightlight-remote.png)
1. `app.py` ফাইলটি ভিএস কোড এক্সপ্লোরারের মাধ্যমে ওপেন করে, নিম্নের কোডটি লিখি
```python
print('Hello World!')
```
এখানে `print` ফাংশনটি এর ভেতরে যা রাখা হবে, তাকে আউটপুট হিসেবে প্রদর্শন করবে।
1. ভিএস কোড টার্মিনাল থেকে নিচের কমান্ডটি রান করানো হলে, পাইথন ফাইলটি রান করবে :
```sh
python3 app.py
```
> 💁 এই কোডটি চালানোর জন্য স্পষ্টভাবে `Python 3` কল করতে হবে কেননা ডিভাইসে যদি পাইথন 3 (সর্বশেষ সংস্করণ) ছাড়াও পাইথন 2 ইনস্টল করা থাকে সেক্ষেত্রে সমস্যা এড়ানোর জন্য। যদি আমাদের পাইথন 2 ইনস্টল থাকে তবে `Python` কল করলে, পাইথন 3 এর পরিবর্তে পাইথন 2 ব্যবহার হবে যা আমাদের অবশ্যই এড়িয়ে চলতে হবে।
টার্মিনালে নিম্নোক্ত আউটপুট দেখাবে :
```output
pi@raspberrypi:~/nightlight $ python3 app.py
Hello World!
```
> 💁 এই সম্পূর্ণ কোডটি পাওয়া যাবে [code/pi](code/pi) ফোল্ডারে ।
😀 আমাদের 'Hello World'প্রোগ্রাম সফল হলো !

@ -66,7 +66,7 @@ An even smarter version could use AI in the cloud with data from other sensors c
Although the I in IoT stands for Internet, these devices don't have to connect to the Internet. In some cases, devices can connect to 'edge' devices - gateway devices that run on your local network meaning you can process data without making a call over the Internet. This can be faster when you have a lot of data or a slow Internet connection, it allows you to run offline where Internet connectivity is not possible such as on a ship or in a disaster area when responding to a humanitarian crisis, and allows you to keep data private. Some devices will contain processing code created using cloud tools and run this locally to gather and respond to data without using an Internet connection to make a decision.
One example of this is a smart home device such as an Apple HomePod, Amazon Alexa, or Google Home, which will listen to your voice using AI models trained in the cloud, and will 'wake up' when a certain word or phrase is spoken, and only then send your speech to the Internet for processing, keeping everything else you say private.
One example of this is a smart home device such as an Apple HomePod, Amazon Alexa, or Google Home, which will listen to your voice using AI models trained in the cloud, but running locally on the device. These devices will 'wake up' when a certain word or phrase is spoken, and only then send your speech over the Internet for processing. The device will stop sending speech at an appropriate point such as when it detects a pause in your speech. Everything you say before waking up the device with the wake word, and everything you say after the device has stopped listening will not be sent over the internet to the device provider, and therefore will be private.
✅ Think of other scenarios where privacy is important so processing of data would be better done on the edge rather than in the cloud. As a hint - think about IoT devices with cameras or other imaging devices on them.

@ -0,0 +1,295 @@
# <div dir="rtl">التعمق أكثر بإنترنت الأشياء</div>
![A sketchnote overview of this lesson](../../../../sketchnotes/lesson-2.png)
> <div dir="rtl"> خريطة من <a href="https://github.com/nitya">Nitya Narasimhan</a> </div>
> <div dir="rtl"> اضغط على الصورة لتكبيرها </div>
</br>
## <div dir="rtl"> اختبار ما قبل المحاضرة </div>
[<div dir="rtl"> اختبار ما قبل المحاضرة </div>](https://brave-island-0b7c7f50f.azurestaticapps.net/quiz/3)
## <div dir="rtl"> المقدمة </div>
<div dir="rtl">
يتعمق هذا الدرس في بعض المفاهيم التي تم تناولها في الدرس الأخير.
سنغطي في هذا الدرس:
* [مكونات تطبيق إنترنت الأشياء](#components-of-an-iot-application)
* [التعمق اكثر في المتحكم الدقيق](#deeper-dive-into-microcontrollers)
* [التعمق اكثر في أجهزة الكمبيوتر ذات اللوحة الواحدة](#deeper-dive-into-single-board-computers)
## مكونات تطبيقات إنترنت الأشياء
المكونان لتطبيق إنترنت الأشياء هما الإنترنت و الشيء. لنلقِ نظرة على هذين المكونين بمزيد من التفصيل.
### الشيء
![A Raspberry Pi 4](../../../../images/raspberry-pi-4.jpg)
***Raspberry Pi 4. Michael Henzler / [Wikimedia Commons](https://commons.wikimedia.org/wiki/Main_Page) / [CC BY-SA 4.0](https://creativecommons.org/licenses/by-sa/4.0/)***
يشير الشيء من إنترنت الأشياء إلى جهاز يمكنه التفاعل مع العالم المادي. عادةً ما تكون هذه الأجهزة أجهزة كمبيوتر صغيرة ومنخفضة السعر ، وتعمل بسرعات منخفضة وتستخدم طاقة منخفضة - على سبيل المثال ، وحدات تحكم دقيقة بسيطة بها كيلوبايت من ذاكرة الوصول العشوائي (على عكس الجيجابايت في جهاز الكمبيوتر) تعمل ببضع مئات من الميجاهرتز فقط (على عكس الجيجاهيرتز) في جهاز كمبيوتر) ، ولكن في بعض الأحيان يستهلك القليل من الطاقة بحيث يمكن تشغيلها لأسابيع أو شهور أو حتى سنوات على البطاريات.
تتفاعل هذه الأجهزة مع العالم المادي ، إما باستخدام أجهزة استشعار لجمع البيانات من محيطها أو عن طريق التحكم في المخرجات أو المحركات لإجراء تغييرات فيزيائية. المثال النموذجي لذلك هو منظم الحرارة الذكي - جهاز يحتوي على مستشعر درجة الحرارة ، ووسيلة لتعيين درجة الحرارة المرغوبة مثل قرص أو شاشة تعمل باللمس ، ووصلة بنظام تدفئة أو تبريد يمكن تشغيله عند اكتشاف درجة الحرارة خارج النطاق المطلوب. يكتشف مستشعر درجة الحرارة أن الغرفة شديدة البرودة ويقوم المشغل بتشغيل التدفئة.
![A diagram showing temperature and a dial as inputs to an IoT device, and control of a heater as an output](../../../../images/basic-thermostat.png)
***A simple thermostat. Temperature by Vectors Market / Microcontroller by Template / dial by Jamie Dickinson / heater by Pascal Heß - all from the [Noun Project](https://thenounproject.com)***
هناك مجموعة كبيرة من الأشياء المختلفة التي يمكن أن تعمل كأجهزة إنترنت الأشياء ، من الأجهزة المخصصة التي تستشعر شيئًا واحدًا ، إلى الأجهزة ذات الأغراض العامة ، حتى هاتفك الذكي! يمكن للهاتف الذكي استخدام المستشعرات لاكتشاف العالم من حوله والمحركات للتفاعل مع العالم - على سبيل المثال ، باستخدام مستشعر GPS لاكتشاف موقعك ومكبر صوت لإعطائك إرشادات التنقل إلى وجهة.
✅ فكر في الأنظمة الأخرى الموجودة حولك والتي تقرأ البيانات من جهاز استشعار وتستخدمها لاتخاذ القرارات. أحد الأمثلة على ذلك هو منظم الحرارة الموجود في الفرن. هل يمكنك إيجاد المزيد؟
</br>
### الانترنت
يتكون جانب الإنترنت من التطبيقات التي يمكن لجهاز إنترنت الأشياء توصيلها لإرسال البيانات واستقبالها ، بالإضافة إلى التطبيقات الأخرى التي يمكنها معالجة البيانات من جهاز إنترنت الأشياء والمساعدة في اتخاذ قرارات بشأن الطلبات التي سيتم إرسالها إلى مشغلات أجهزة إنترنت الأشياء.
يتمثل أحد الإعدادات النموذجية في وجود نوع من الخدمة السحابية التي يتصل بها جهاز إنترنت الأشياء ، وتتولى هذه الخدمة السحابية أشياء مثل الأمان ، بالإضافة إلى تلقي الرسائل من جهاز إنترنت الأشياء ، وإرسال الرسائل مرة أخرى إلى الجهاز. ستتصل هذه الخدمة السحابية بعد ذلك بالتطبيقات الأخرى التي يمكنها معالجة بيانات المستشعر أو تخزينها ، أو استخدام بيانات المستشعر مع البيانات من الأنظمة الأخرى لاتخاذ القرارات.
لا تتصل الأجهزة دائمًا مباشرة بالإنترنت عبر شبكة WiFi أو اتصالات سلكية. تستخدم بعض الأجهزة الشبكات المتداخلة للتحدث مع بعضها البعض عبر تقنيات مثل Bluetooth ، والاتصال عبر جهاز لوحة وصل متصل بالإنترنت.
باستخدام مثال منظم الحرارة الذكي ، سيتصل منظم الحرارة باستخدام شبكة WiFi المنزلية بخدمة سحابية تعمل في السحابة. سيرسل بيانات درجة الحرارة إلى هذه الخدمة السحابية ، ومن هناك ستتم كتابتها في قاعدة بيانات بشكل يسمح لمالك المنزل بالتحقق من درجات الحرارة الحالية والسابقة باستخدام تطبيق الهاتف. ستعرف خدمة أخرى في السحابة درجة الحرارة التي يريدها صاحب المنزل ، وترسل الرسائل مرة أخرى إلى جهاز إنترنت الأشياء عبر الخدمة السحابية لإخبار نظام التدفئة بالتشغيل أو الإيقاف.
![A diagram showing temperature and a dial as inputs to an IoT device, the IoT device with 2 way communication to the cloud, which in turn has 2 way communication to a phone, and control of a heater as an output from the IoT device](../../../../images/mobile-controlled-thermostat.png)
***An Internet connected thermostat with mobile app control. Temperature by Vectors Market / Microcontroller by Template / dial by Jamie Dickinson / heater by Pascal Heß / mobile phone by Alice-vector / Cloud by Debi Alpa Nugraha - all from the [Noun Project](https://thenounproject.com)***
يمكن لنسخة أكثر ذكاءً استخدام الذكاء الاصطناعي في السحابة مع بيانات من مستشعرات أخرى متصلة بأجهزة إنترنت الأشياء الأخرى مثل مستشعرات الإشغال التي تكتشف الغرف المستخدمة ، بالاضافة الى البيانات مثل الطقس وحتى التقويم الخاص بك ، لاتخاذ قرارات بشأن كيفية ضبط درجة الحرارة بطريقة ذكية. على سبيل المثال ، يمكن أن يوقف التدفئة إذا كان يقرأ من التقويم الخاص بك أنك في إجازة ، أو أيقاف التدفئة على أساس كل غرفة على حدة اعتمادًا على الغرف التي تستخدمها ، والتعلم من البيانات لتكون أكثر دقة بمرور الوقت .
![A diagram showing multiple temperature sensors and a dial as inputs to an IoT device, the IoT device with 2 way communication to the cloud, which in turn has 2 way communication to a phone, a calendar and a weather service, and control of a heater as an output from the IoT device](../../../../images/smarter-thermostat.png)
***An Internet connected thermostat using multiple room sensors, with mobile app control, as well as intelligence from weather and calendar data. Temperature by Vectors Market / Microcontroller by Template / dial by Jamie Dickinson / heater by Pascal Heß / mobile phone and Calendar by Alice-vector / Cloud by Debi Alpa Nugraha / smart sensor by Andrei Yushchenko / weather by Adrien Coquet - all from the [Noun Project](https://thenounproject.com)***
✅ ما هي البيانات الأخرى التي يمكن أن تساعد في جعل منظم الحرارة المتصل بالإنترنت أكثر ذكاءً؟
</br>
### إنترنت الأشياء على edge
على الرغم من أن انترنت الاشياء تعني الإنترنت ، إلا أن هذه الأجهزة لا تحتاج إلى الاتصال بالإنترنت. في بعض الحالات ، يمكن للأجهزة الاتصال بأجهزة "edge" - أجهزة البوابة التي تعمل على شبكتك المحلية مما يعني أنه يمكنك معالجة البيانات دون إجراء مكالمة عبر الإنترنت. يمكن أن يكون هذا أسرع عندما يكون لديك الكثير من البيانات أو يكون اتصال الإنترنت بطيئًا ، فهو يسمح لك بالعمل دون اتصال بالإنترنت حيث يكون الاتصال بالإنترنت غير ممكن كما هو الحال على متن سفينة أو في منطقة كوارث عند الاستجابة لأزمة إنسانية ، ويسمح لك الحفاظ على خصوصية البيانات. ستحتوي بعض الأجهزة على كود معالجة تم إنشاؤه باستخدام أدوات السحابة وتشغيله محليًا لجمع البيانات والاستجابة لها دون استخدام اتصال بالإنترنت لاتخاذ قرار.
أحد الأمثلة على ذلك هو جهاز منزلي ذكي مثل Apple HomePod أو Amazon Alexa أو Google Home ، والتي ستستمع إلى صوتك باستخدام نماذج AI المدربة في السحابة ، ولكنها تعمل محليًا على الجهاز. سوف "تستيقظ" هذه الأجهزة عند نطق كلمة أو عبارة معينة ، وعندها فقط ترسل كلامك عبر الإنترنت لمعالجته. سيتوقف الجهاز عن إرسال الكلام في نقطة مناسبة مثل عندما يكتشف توقفًا مؤقتًا في كلامك. كل ما تقوله قبل إيقاظ الجهاز بكلمة التنبيه ، وكل ما تقوله بعد توقف الجهاز عن الاستماع لن يتم إرساله عبر الإنترنت إلى مزود الجهاز ، وبالتالي سيكون خاصًا.
✅ فكر في سيناريوهات أخرى حيث تكون الخصوصية مهمة ، لذا من الأفضل إجراء معالجة البيانات على edge بدلاً من السحابة. كتلميح - فكر في أجهزة إنترنت الأشياء المزودة بكاميرات أو أجهزة تصوير أخرى عليها.
</br>
### أمن إنترنت الأشياء
مع أي اتصال بالإنترنت ، يعد الأمان أحد الاعتبارات المهمة. هناك مزحة قديمة مفادها أن "S in IoT تعني الأمان" - لا يوجد حرف "S" في إنترنت الأشياء ، مما يعني أنه ليس آمنًا.
تتصل أجهزة إنترنت الأشياء بالخدمة السحابية ، وبالتالي فهي آمنة فقط مثل تلك الخدمة السحابية - إذا كانت الخدمة السحابية الخاصة بك تسمح لأي جهاز بالاتصال ، فيمكن إرسال البيانات الضارة ، أو يمكن أن تحدث هجمات الفيروسات. يمكن أن يكون لهذا عواقب حقيقية للغاية حيث تتفاعل أجهزة إنترنت الأشياء وتتحكم في الأجهزة الأخرى. على سبيل المثال ، ملف <a href="https://wikipedia.org/wiki/Stuxnet">Stuxnet worm</a> التلاعب بالصمامات في أجهزة الطرد المركزي لإتلافها. استفاد القراصنة أيضًا من <a href="https://www.npr.org/sections/thetwo-way/2018/06/05/617196788/s-c-mom-says-baby-monitor-was-hacked-experts-say-many-devices-are-vulnerable">ضعف الأمن للوصول إلى أجهزة مراقبة الأطفال</a> وأجهزة المراقبة المنزلية الأخرى.
> 💁 في بعض الأحيان ، تعمل أجهزة إنترنت الأشياء والأجهزة الطرفية على شبكة معزولة تمامًا عن الإنترنت للحفاظ على خصوصية البيانات وأمانها. هذا هو المعروف باسم <a href="https://wikipedia.org/wiki/Air_gap_(networking)">air-gapping</a>.
</br>
### التعمق اكثر في المتحكم الدقيق
في الدرس الأخير ، قدمنا المتحكمات الدقيقة. دعونا الآن نلقي نظرة أعمق عليهم.
</br>
### وحدة المعالجة المركزية
وحدة المعالجة المركزية هي "عقل" المتحكم الدقيق. إنه المعالج الذي يقوم بتشغيل الكود الخاص بك ويمكنه إرسال البيانات واستقبال البيانات من أي أجهزة متصلة. يمكن أن تحتوي وحدات المعالجة المركزية (CPU) على مركز واحد أو أكثر - وحدة معالجة مركزية واحدة أو أكثر يمكنها العمل معًا لتشغيل التعليمات البرمجية الخاصة بك.
تعتمد وحدات المعالجة المركزية (CPU) على ساعة لتحديد عدة ملايين أو مليارات المرات في الثانية. تقوم كل علامة أو دورة بمزامنة الإجراءات التي يمكن أن تتخذها وحدة المعالجة المركزية. مع كل علامة ، يمكن لوحدة المعالجة المركزية تنفيذ تعليمات من أحد البرامج ، مثل استرداد البيانات من جهاز خارجي أو إجراء عملية حسابية. تسمح هذه الدورة المنتظمة بإكمال جميع الإجراءات قبل معالجة التعليمات التالية.
كلما كانت دورة الساعة أسرع ، زادت التعليمات التي يمكن معالجتها كل ثانية ، وبالتالي زادت سرعة وحدة المعالجة المركزية. يتم قياس سرعات وحدة المعالجة المركزية بـ<a href="https://wikipedia.org/wiki/Hertz">Hertz (Hz)</a> ،وحدة قياسية حيث 1 هرتز يعني دورة واحدة أو علامة ساعة في الثانية.
> 🎓 سرعات وحدة المعالجة المركزية تُعطى غالبًا بالميغاهرتز أو الجيجاهرتز. 1 ميجا هرتز هو 1 مليون هرتز ، 1 جيجا هرتز 1 مليار هرتز.
> 💁 تنفذ وحدات المعالجة المركزية البرامج باستخدام امتداد <a href="https://wikipedia.org/wiki/Instruction_cycle">fetch-decode-execute cycle)</a> . لكل علامة ساعة ، ستقوم وحدة المعالجة المركزية بجلب التعليمات التالية من الذاكرة ، وفك تشفيرها ، ثم تنفيذها مثل استخدام وحدة المنطق الحسابي (ALU) لإضافة رقمين. ستستغرق بعض عمليات التنفيذ عدة علامات للتشغيل ، لذا ستعمل الدورة التالية عند العلامة التالية بعد اكتمال التعليمات.
![The fetch decode execute cycles showing the fetch taking an instruction from the program stored in RAM, then decoding and executing it on a CPU](../../../../images/fetch-decode-execute.png)
***CPU by Icon Lauk / ram by Atif Arshad - all from the [Noun Project](https://thenounproject.com)***
تتميز المتحكمات الدقيقة بسرعات ساعة أقل بكثير من أجهزة الكمبيوتر المكتبية أو المحمولة ، أو حتى معظم الهواتف الذكية. تحتوي Wio Terminal على سبيل المثال على وحدة معالجة مركزية تعمل بسرعة 120 ميجاهرتز أو 120.000.000 دورة في الثانية.
✅ يحتوي الكمبيوتر الشخصي العادي أو جهاز Mac على وحدة معالجة مركزية متعددة النوى تعمل بسرعة جيجاهرتز متعددة ، مما يعني أن الساعة تدق مليارات المرات في الثانية. ابحث في سرعة الساعة لجهاز الكمبيوتر الخاص بك وقارن عدد المرات التي تكون فيها أسرع من محطة Wio.
تقوم كل دورة على مدار الساعة بسحب الطاقة وتوليد الحرارة. كلما زادت سرعة ضربات الساعة ، زادت الطاقة المستهلكة والمزيد من الحرارة المتولدة. تحتوي أجهزة الكمبيوتر على أحواض حرارية ومراوح لإزالة الحرارة ، والتي بدونها سوف ترتفع درجة حرارتها وتغلق في غضون ثوانٍ. غالبًا ما لا تحتوي المتحكمات الدقيقة على أي منهما لأنها تعمل بشكل أكثر برودة وبالتالي فهي أبطأ بكثير. نفد التيار الكهربائي للكمبيوتر الشخصي أو البطاريات الكبيرة لبضع ساعات ، يمكن أن تعمل وحدات التحكم الدقيقة لأيام أو شهور أو حتى سنوات من البطاريات الصغيرة. يمكن أن تحتوي وحدات التحكم الدقيقة أيضًا على نوى تعمل بسرعات مختلفة ، وتتحول إلى نوى منخفضة الطاقة أبطأ عندما يكون الطلب على وحدة المعالجة المركزية منخفضًا لتقليل استهلاك الطاقة.
> 💁 تتبنى بعض أجهزة الكمبيوتر الشخصية وأجهزة Mac نفس المزيج من النوى السريعة عالية الطاقة ونواتج الطاقة المنخفضة الأبطأ ، مع التبديل لتوفير البطارية. على سبيل المثال ، يمكن لشريحة M1 في أحدث أجهزة كمبيوتر Apple المحمولة التبديل بين 4 نوى أداء و 4 نوى كفاءة لتحسين عمر البطارية أو سرعتها اعتمادًا على المهمة التي يتم تشغيلها.
✅ قم ببعض البحث: اقرأ عن وحدات المعالجة المركزية في <a href="https://wikipedia.org/wiki/Central_processing_unit">Wikipedia CPU article </a>
### مهمة
تحقق من محطة Wio.
إذا كنت تستخدم Wio Terminal لهذه الدروس ، فحاول العثور على وحدة المعالجة المركزية. ابحث عن قسم نظرة عامة على الأجهزة في <a href="https://www.seeedstudio.com/Wio-Terminal-p-4509.html">Wio Terminal product page </a> للحصول على صورة للأجزاء الداخلية ، وحاول العثور على وحدة المعالجة المركزية من خلال النافذة البلاستيكية الشفافة الموجودة في الخلف.
### ذاكرة
عادة ما تحتوي المتحكمات الدقيقة على نوعين من الذاكرة - ذاكرة البرنامج وذاكرة الوصول العشوائي (RAM).
ذاكرة البرنامج غير متطايرة ، مما يعني أن كل ما هو مكتوب عليها يبقى عند عدم وجود طاقة للجهاز. هذه هي الذاكرة التي تخزن كود البرنامج الخاص بك.
ذاكرة الوصول العشوائي هي الذاكرة التي يستخدمها البرنامج للتشغيل ، وتحتوي على متغيرات يخصصها برنامجك وبيانات تم جمعها من الأجهزة الطرفية. ذاكرة الوصول العشوائي متقلبة ، عندما تنقطع الطاقة تضيع المحتويات ، مما يؤدي إلى إعادة ضبط البرنامج بشكل فعال.
> 🎓 ذاكرة البرنامج تخزن الكود الخاص بك وتبقى عند انقطاع التيار الكهربائي.
> 🎓 تُستخدم ذاكرة الوصول العشوائي (RAM) لتشغيل برنامجك وتتم إعادة تعيينها عند انقطاع التيار الكهربائي
كما هو الحال مع وحدة المعالجة المركزية ، فإن الذاكرة الموجودة على وحدة التحكم الدقيقة هي أصغر من أجهزة الكمبيوتر الشخصي أو جهاز Mac. قد يحتوي جهاز الكمبيوتر العادي على 8 جيجا بايت من ذاكرة الوصول العشوائي ، أو 8000 مليون بايت ، مع مساحة كافية لكل بايت لتخزين حرف واحد أو رقم من 0-255. سيكون للمتحكم الدقيق فقط كيلو بايت (KB) من ذاكرة الوصول العشوائي ، مع كيلو بايت يبلغ 1000 بايت. تحتوي محطة Wio المذكورة أعلاه على 192 كيلو بايت من ذاكرة الوصول العشوائي ، أو 192000 بايت - أي أكثر من 40000 مرة أقل من متوسط ​​الكمبيوتر الشخصي!
يوضح الرسم البياني أدناه اختلاف الحجم النسبي بين 192 كيلو بايت و 8 جيجابايت - تمثل النقطة الصغيرة في المنتصف 192 كيلو بايت.
![A comparison between 192KB and 8GB - more than 40,000 times larger](../../../../images/ram-comparison.png)
تخزين البرنامج أصغر أيضًا من جهاز الكمبيوتر. قد يحتوي جهاز الكمبيوتر العادي على محرك أقراص ثابت سعة 500 جيجابايت لتخزين البرنامج ، في حين أن وحدة التحكم الدقيقة قد تحتوي على كيلوبايت فقط أو ربما بضعة ميغا بايت (MB) من التخزين (1 ميجابايت تساوي 1،000 كيلو بايت ، أو 1000000 بايت). محطة Wio لديها 4 ميغا بايت من تخزين البرنامج.
✅ قم بإجراء بحث بسيط: ما مقدار ذاكرة الوصول العشوائي ومساحة التخزين التي يمتلكها الكمبيوتر الذي تستخدمه لقراءة هذا؟ كيف يقارن هذا بالمتحكم الدقيق؟
### الإدخال / الإخراج
تحتاج المتحكمات الدقيقة إلى توصيلات الإدخال والإخراج (I / O) لقراءة البيانات من أجهزة الاستشعار وإرسال إشارات التحكم إلى المشغلات. عادة ما تحتوي على عدد من دبابيس الإدخال / الإخراج للأغراض العامة (GPIO). يمكن تكوين هذه المسامير في البرنامج بحيث يتم إدخالها (أي أنها تتلقى إشارة) ، أو إخراج (ترسل إشارة).
🧠⬅️ تُستخدم دبابيس الإدخال لقراءة القيم من أجهزة الاستشعار
🧠➡️ ترسل دبابيس الإخراج التعليمات إلى المشغلات
✅ سوف تتعلم المزيد عن هذا في درس لاحق.
#### مهمة
تحقق من محطة Wio.
إذا كنت تستخدم Wio Terminal لهذه الدروس ، فابحث عن دبابيس GPIO. ابحث عن قسم Pinout diagram في ملف <a href="https://www.seeedstudio.com/Wio-Terminal-p-4509.html">Wio Terminal product page </a> لمعرفة الدبابيس التي. تأتي Wio Terminal مع ملصق يمكنك تثبيته على ظهره بأرقام الدبوس ، لذا أضف هذا الآن إذا لم تكن قد قمت بذلك بالفعل.
### حجم فيزيائي
عادة ما تكون المتحكمات الدقيقة صغيرة الحجم ، وأصغرها <a href="https://www.edn.com/tiny-arm-cortex-m0-based-mcu-shrinks-package/">Freescale Kinetis KL03 MCU صغير بما يكفي ليلائم غمازة كرة الجولف </a> . يمكن لوحدة المعالجة المركزية في جهاز الكمبيوتر فقط قياس 40 مم × 40 مم ، وهذا لا يشمل المشتتات الحرارية والمراوح اللازمة لضمان تشغيل وحدة المعالجة المركزية لأكثر من بضع ثوانٍ دون ارتفاع درجة الحرارة ، وهي أكبر بكثير من وحدة تحكم دقيقة كاملة. إن مجموعة مطور Wio الطرفية المزودة بوحدة تحكم دقيقة وحالة وشاشة ومجموعة من التوصيلات والمكونات ليست أكبر بكثير من وحدة المعالجة المركزية Intel i9 ، وهي أصغر بكثير من وحدة المعالجة المركزية مع المشتت الحراري والمروحة!
| الجهاز | الحجم |
| ------------------------------- | --------------------- |
| Freescale Kinetis KL03 | 1.6 مم × 2 مم × 1 مم |
| محطة Wio | 72 مم × 57 مم × 12 مم |
| وحدة المعالجة المركزية Intel i9 ، المشتت الحراري والمروحة | 136 مم × 145 مم × 103 مم |
### أنظمة التشغيل
نظرًا لانخفاض سرعتها وحجم الذاكرة ، لا تقوم وحدات التحكم الدقيقة بتشغيل نظام تشغيل (OS) بمعنى سطح المكتب . يحتاج نظام التشغيل الذي يعمل على تشغيل الكمبيوتر (Windows أو Linux أو macOS) إلى قدر كبير من الذاكرة وقوة المعالجة لتشغيل المهام غير الضرورية تمامًا لوحدة التحكم الدقيقة. تذكر أن المتحكمات الدقيقة عادة ما تكون مبرمجة لأداء مهمة واحدة أو أكثر من المهام المحددة للغاية ، على عكس أجهزة الكمبيوتر ذات الأغراض العامة مثل الكمبيوتر الشخصي أو جهاز Mac الذي يحتاج إلى دعم واجهة المستخدم أو تشغيل الموسيقى أو الأفلام أو توفير أدوات لكتابة المستندات أو التعليمات البرمجية أو ممارسة الألعاب أو تصفح الانترنت.
لبرمجة متحكم دقيق بدون نظام تشغيل ، فأنت بحاجة إلى بعض الأدوات للسماح لك ببناء الكود الخاص بك بطريقة يمكن للميكروكونترولر تشغيلها ، باستخدام واجهات برمجة التطبيقات التي يمكنها التحدث إلى أي أجهزة طرفية. يختلف كل متحكم عن الآخر ، لذا فإن الشركات المصنعة تدعم عادةً الأطر القياسية التي تسمح لك باتباع "وصفة" قياسية لبناء الكود الخاص بك وتشغيله على أي متحكم يدعم هذا الإطار.
يمكنك برمجة وحدات التحكم الدقيقة باستخدام نظام تشغيل - يشار إليه غالبًا باسم نظام التشغيل في الوقت الفعلي (RTOS) ، حيث تم تصميمه للتعامل مع إرسال البيانات من وإلى الأجهزة الطرفية في الوقت الفعلي. تتميز أنظمة التشغيل هذه بأنها خفيفة الوزن للغاية وتوفر ميزات مثل:
* خيوط متعددة ، مما يسمح للكود الخاص بك بتشغيل أكثر من كتلة واحدة من التعليمات البرمجية في نفس الوقت ، إما على مراكز متعددة أو بالتناوب على نواة واحدة
* الشبكات للسماح بالاتصال عبر الإنترنت بشكل آمن
* مكونات واجهة المستخدم الرسومية (GUI) لبناء واجهات المستخدم (UI) على الأجهزة التي تحتوي على شاشات.
✅ اقرأ عن بعض أنظمة RTOS المختلفة:
<a href="https://azure.microsoft.com/services/rtos/?WT.mc_id=academic-17441-jabenn">Azure RTOS </a>, <a href="https://www.freertos.org">FreeRTOS </a> , <a href="https://www.zephyrproject.org">Zephyr </a>
</br>
#### Arduino
![The Arduino logo](../../../../images/arduino-logo.svg)
<a href="https://www.arduino.cc">Arduino </a>
من المحتمل أن يكون إطار عمل وحدة التحكم الدقيقة الأكثر شيوعًا ، خاصة بين الطلاب والهواة والصناع. Arduino عبارة عن منصة إلكترونية مفتوحة المصدر تجمع بين البرامج والأجهزة. يمكنك شراء لوحات Arduino المتوافقة من Arduino نفسها أو من الشركات المصنعة الأخرى ، ثم كتابة التعليمات البرمجية باستخدام إطار عمل Arduino.
يتم ترميز لوحات Arduino في C أو C ++. يتيح استخدام C / C ++ تجميع التعليمات البرمجية الخاصة بك بشكل صغير جدًا وتشغيلها بسرعة ، وهو شيء مطلوب على جهاز مقيد مثل متحكم دقيق. يُشار إلى جوهر تطبيق Arduino بالرسم وهو رمز C / C ++ مع وظيفتين - "الإعداد" و "الحلقة". عند بدء تشغيل اللوحة ، سيعمل كود إطار عمل Arduino على تشغيل وظيفة "الإعداد" مرة واحدة ، ثم يقوم بتشغيل وظيفة "الحلقة" مرارًا وتكرارًا ، وتشغيلها باستمرار حتى يتم إيقاف تشغيل الطاقة.
ستكتب رمز الإعداد الخاص بك في وظيفة "الإعداد" ، مثل الاتصال بشبكة WiFi والخدمات السحابية أو تهيئة المسامير للإدخال والإخراج. سيحتوي رمز الحلقة الخاص بك بعد ذلك على رمز معالجة ، مثل القراءة من جهاز استشعار وإرسال القيمة إلى السحابة. يمكنك عادةً تضمين تأخير في كل حلقة ، على سبيل المثال ، إذا كنت تريد فقط إرسال بيانات المستشعر كل 10 ثوانٍ ، فستضيف تأخيرًا لمدة 10 ثوانٍ في نهاية الحلقة حتى يتمكن المتحكم الدقيق من السكون ، وتوفير الطاقة ، ثم التشغيل الحلقة مرة أخرى عند الحاجة بعد 10 ثوانٍ.
![An arduino sketch running setup first, then running loop repeatedly](../../../../images/arduino-sketch.png)
✅ تُعرف بنية البرنامج هذه باسم حلقة الحدث أو حلقة الرسالة . تستخدم العديد من التطبيقات هذا تحت الغطاء وهو المعيار لمعظم تطبيقات سطح المكتب التي تعمل على أنظمة تشغيل مثل Windows أو macOS أو Linux. "الحلقة" تستمع إلى الرسائل الواردة من مكونات واجهة المستخدم مثل الأزرار أو الأجهزة مثل لوحة المفاتيح وتستجيب لها. يمكنك قراءة المزيد في هذا <a href="https://wikipedia.org/wiki/Event_loop">article on the event loop </a>
يوفر Arduino مكتبات قياسية للتفاعل مع وحدات التحكم الدقيقة ودبابيس الإدخال / الإخراج ، مع تطبيقات مختلفة أسفل الغطاء للتشغيل على وحدات تحكم دقيقة مختلفة. على سبيل المثال ، ملف <a href="https://www.arduino.cc/reference/en/language/functions/time/delay/">`delay` function </a> سيوقف البرنامج مؤقتًا لفترة معينة من الوقت ، فإن <a href="https://www.arduino.cc/reference/en/language/functions/digital-io/digitalread/">`digitalRead` function </a> سيقرأ قيمة "HIGH" أو "LOW" من رقم التعريف الشخصي المحدد ، بغض النظر عن اللوحة التي يتم تشغيل الكود عليها. تعني هذه المكتبات القياسية أن كود Arduino المكتوب للوحة واحدة يمكن إعادة تجميعه لأي لوحة Arduino أخرى وسيتم تشغيله ، على افتراض أن الدبابيس هي نفسها وأن اللوحات تدعم نفس الميزات.
يوجد نظام بيئي كبير من مكتبات Arduino الخارجية يسمح لك بإضافة ميزات إضافية إلى مشاريع Arduino الخاصة بك ، مثل استخدام المستشعرات والمشغلات أو الاتصال بخدمات إنترنت الأشياء السحابية.
##### مهمة
تحقق من محطة Wio.
إذا كنت تستخدم Wio Terminal لهذه الدروس ، فأعد قراءة الكود الذي كتبته في الدرس الأخير. ابحث عن وظيفتي "الإعداد" و "الحلقة". راقب الإخراج التسلسلي لوظيفة الحلقة التي يتم استدعاؤها بشكل متكرر. حاول إضافة رمز إلى وظيفة "الإعداد" للكتابة إلى المنفذ التسلسلي ولاحظ أن هذا الرمز يتم استدعاؤه مرة واحدة فقط في كل مرة تقوم فيها بإعادة التشغيل. حاول إعادة تشغيل جهازك باستخدام مفتاح الطاقة الموجود على الجانب لإظهار أن هذا يسمى في كل مرة يتم فيها إعادة تشغيل الجهاز.
## التعمق اكثر في أجهزة الكمبيوتر ذات اللوحة الواحد
في الدرس الأخير ، قدمنا أجهزة كمبيوتر أحادية اللوحة. دعونا الآن نلقي نظرة أعمق عليهم.
### Raspberry Pi
![The Raspberry Pi logo](../../../../images/raspberry-pi-logo.png)
<a href="https://www.raspberrypi.org">Raspberry Pi Foundation </a> هي مؤسسة خيرية من المملكة المتحدة تأسست عام 2009 للترويج لدراسة علوم الكمبيوتر ، وخاصة على مستوى المدرسة. كجزء من هذه المهمة ، قاموا بتطوير جهاز كمبيوتر ذو لوحة واحدة ، يسمى Raspberry Pi. يتوفر Raspberry Pi حاليًا في 3 متغيرات - إصدار بالحجم الكامل ، و Pi Zero الأصغر ، ووحدة حسابية يمكن دمجها في جهاز IoT النهائي الخاص بك.
![A Raspberry Pi 4](../../../../images/raspberry-pi-4.jpg)
***Raspberry Pi 4. Michael Henzler / [Wikimedia Commons](https://commons.wikimedia.org/wiki/Main_Page) / [CC BY-SA 4.0](https://creativecommons.org/licenses/by-sa/4.0/)***
أحدث نسخة من Raspberry Pi بالحجم الكامل هي Raspberry Pi 4B. يحتوي هذا على وحدة معالجة مركزية رباعية النواة (4 نواة) تعمل بسرعة 1.5 جيجاهرتز أو 2 أو 4 أو 8 جيجابايت من ذاكرة الوصول العشوائي و Gigabit ethernet و WiFi ومنفذين HDMI يدعمان شاشات 4K ومنفذ إخراج الصوت والفيديو المركب ومنافذ USB (2 USB 2.0 ، 2 USB 3.0) ، 40 GPIO ، موصل كاميرا لوحدة كاميرا Raspberry Pi ، وفتحة بطاقة SD. كل هذا على لوحة مقاس 88 مم × 58 مم × 19.5 مم ويتم تشغيلها بواسطة مصدر طاقة 3 أمبير USB-C. يبدأ سعرها من 35 دولارًا أمريكيًا ، وهو أرخص بكثير من جهاز الكمبيوتر الشخصي أو جهاز Mac.
> 💁 يوجد أيضًا جهاز كمبيوتر Pi400 الكل في واحد مع Pi4 المدمج في لوحة المفاتيح.
![A Raspberry Pi Zero](../../../../images/raspberry-pi-zero.jpg)
Pi Zero أصغر بكثير ، مع طاقة أقل. يحتوي على وحدة معالجة مركزية أحادية النواة بسرعة 1 جيجاهرتز ، وذاكرة وصول عشوائي (RAM) سعة 512 ميجابايت ، و WiFi (في طراز Zero W) ، ومنفذ HDMI واحد ، ومنفذ micro-USB ، و 40 دبوس GPIO ، وموصل كاميرا لوحدة كاميرا Raspberry Pi ، وبطاقة SD فتحة. يقيس 65 مم × 30 مم × 5 مم ، ولا يستهلك سوى القليل من الطاقة. سعر Zero 5 دولارات أمريكية ، مع إصدار W مع شبكة WiFi بقيمة 10 دولارات أمريكية.
> 🎓 وحدات المعالجة المركزية في كلاهما هي معالجات ARM ، على عكس معالجات Intel / AMD x86 أو x64 التي تجدها في معظم أجهزة الكمبيوتر الشخصية وأجهزة Mac. هذه تشبه وحدات المعالجة المركزية التي تجدها في بعض المتحكمات الدقيقة ، وكذلك جميع الهواتف المحمولة تقريبًا ، ومايكروسوفت سيرفس إكس ، وأجهزة آبل ماك الجديدة القائمة على السيليكون.
تعمل جميع متغيرات Raspberry Pi على إصدار من Debian Linux يسمى Raspberry Pi OS. يتوفر هذا كإصدار خفيف بدون سطح مكتب ، وهو مثالي لمشروعات "بلا رأس" حيث لا تحتاج إلى شاشة ، أو نسخة كاملة مع بيئة سطح مكتب كاملة ، مع متصفح الويب ، والتطبيقات المكتبية ، وأدوات الترميز والألعاب. نظرًا لأن نظام التشغيل هو إصدار من Debian Linux ، يمكنك تثبيت أي تطبيق أو أداة تعمل على Debian ومصممة لمعالج ARM داخل Pi.
#### مهمة
تحقق من Raspberry Pi.
إذا كنت تستخدم Raspberry Pi لهذه الدروس ، فاقرأ عن مكونات الأجهزة المختلفة الموجودة على اللوحة.
* يمكنك العثور على تفاصيل حول المعالجات المستخدمة في <a href="https://www.raspberrypi.org/documentation/hardware/raspberrypi/">Raspberry Pi hardware documentation page </a> اقرأ عن المعالج المستخدم في Pi الذي تستخدمه.
* حدد موقع دبابيس GPIO. اقرأ المزيد عنها في <a href="https://www.raspberrypi.org/documentation/hardware/raspberrypi/gpio/README.md">Raspberry Pi GPIO documentation </a> . استخدم <a href="https://www.raspberrypi.org/documentation/usage/gpio/README.md">GPIO Pin Usage guide </a> لتحديد الدبابيس المختلفة على Pi الخاص بك.
### برمجة أجهزة الكمبيوتر ذات اللوحة الواحدة
أجهزة الكمبيوتر أحادية اللوحة هي أجهزة كمبيوتر كاملة تعمل بنظام تشغيل كامل. هذا يعني أن هناك مجموعة واسعة من لغات البرمجة والأطر والأدوات التي يمكنك استخدامها لترميزها ، على عكس المتحكمات الدقيقة التي تعتمد على دعم اللوحة في أطر مثل Arduino. تحتوي معظم لغات البرمجة على مكتبات يمكنها الوصول إلى دبابيس GPIO لإرسال واستقبال البيانات من أجهزة الاستشعار والمشغلات.
✅ ما هي لغات البرمجة التي تعرفها؟ هل هم مدعومون على لينكس؟
لغة البرمجة الأكثر شيوعًا لبناء تطبيقات إنترنت الأشياء على Raspberry Pi هي Python. يوجد نظام بيئي ضخم للأجهزة المصممة لـ Pi ، وكلها تقريبًا تشتمل على الكود ذي الصلة اللازم لاستخدامها كمكتبات Python. تعتمد بعض هذه الأنظمة البيئية على "القبعات" - وهذا ما يسمى لأنها تجلس على قمة Pi مثل القبعة وتتصل بمقبس كبير إلى 40 دبوس GPIO. توفر هذه القبعات إمكانات إضافية ، مثل الشاشات أو المستشعرات أو السيارات التي يتم التحكم فيها عن بُعد أو المحولات للسماح لك بتوصيل المستشعرات بكابلات قياسية
### استخدام أجهزة الكمبيوتر أحادية اللوحة في عمليات نشر إنترنت الأشياء الاحترافية
تُستخدم أجهزة الكمبيوتر أحادية اللوحة في عمليات نشر إنترنت الأشياء الاحترافية ، وليس فقط كمجموعات للمطورين. يمكن أن توفر طريقة قوية للتحكم في الأجهزة وتشغيل المهام المعقدة مثل تشغيل نماذج التعلم الآلي. على سبيل المثال ، <a href="https://www.raspberrypi.org/blog/raspberry-pi-compute-module-4/">Raspberry Pi 4 compute module </a> توفر كل قوة Raspberry Pi 4 ولكن في عامل شكل مدمج وأرخص بدون معظم المنافذ ، مصمم ليتم تثبيته في الأجهزة المخصصة.
---
## 🚀 تحدي
كان التحدي في الدرس الأخير هو سرد أكبر عدد ممكن من أجهزة إنترنت الأشياء الموجودة في منزلك أو مدرستك أو مكان عملك. لكل جهاز في هذه القائمة ، هل تعتقد أنه مبني على وحدات تحكم دقيقة أو أجهزة كمبيوتر أحادية اللوحة ، أو حتى مزيج من الاثنين؟
## مسابقة ما بعد المحاضرة
[<div dir="rtl"> اختبار ما بعد المحاضرة </div>](https://brave-island-0b7c7f50f.azurestaticapps.net/quiz/4)
## مراجعة ودراسة ذاتية
* اقرأ <a href="https://www.arduino.cc/en/Guide/Introduction">Arduino getting started guide </a> لفهم المزيد حول نظام Arduino الأساسي.
* اقرأ <a href="https://www.raspberrypi.org/products/raspberry-pi-4-model-b/">introduction to the Raspberry Pi 4</a> لمعرفة المزيد عن Raspberry Pi.
✅ استخدم هذه الأدلة ، جنبًا إلى جنب مع التكاليف الموضحة باتباع الروابط الموجودة في ملف [hardware guide](../../../hardware.md) لتحديد النظام الأساسي للأجهزة الذي تريد استخدامه ، أو إذا كنت تفضل استخدام جهاز افتراضي.
## واجب
[قارن بين المتحكمات الدقيقة وأجهزة الكمبيوتر أحادية اللوحة](assignment.ar.md)
</div>

@ -0,0 +1,16 @@
<div dir="rtl">
# قارن بين المتحكمات الدقيقة وأجهزة الكمبيوتر أحادية اللوحة
## التعليمات
غطى هذا الدرس المتحكمات الدقيقة وأجهزة الكمبيوتر أحادية اللوحة. قم بإنشاء جدول لمقارنتها ، ولاحظ على الأقل سببين لاستخدام متحكم دقيق على جهاز كمبيوتر ذي لوحة واحدة ، وسببين على الأقل لاستخدام جهاز كمبيوتر من لوحة واحدة بدلاً من متحكم دقيق.
## نماذج
| معايير | نموذجي | مناسب | يحتاج الى تحسين |
| -------- | --------- | -------- | ----------------- |
| قم بإنشاء جدول يقارن المتحكمات الدقيقة بأجهزة الكمبيوتر أحادية اللوحة | إنشاء قائمة بالعناصر المتعددة للمقارنة والتباين بشكل صحيح | تم إنشاء قائمة تحتوي على عنصرين فقط | كان قادرًا على الخروج بعنصر واحد فقط ، أو لا توجد عناصر للمقارنة والتباين |
| أسباب استخدام أحدهما على الآخر | كان قادرًا على تقديم سببين أو أكثر لاجهزة التحكم الدقيق ، وسببين أو أكثر لأجهزة الكمبيوتر ذات اللوحة الواحدة | كان قادرًا فقط على تقديم 1-2 سبب لمتحكم دقيق ، وسببين أو اكثر لجهاز كمبيوتر لوحة واحدة | لم يكن قادرًا على تقديم سبب واحد أو أكثر لمتحكم دقيق أو لجهاز كمبيوتر أحادي اللوحة |
<div>

@ -95,7 +95,7 @@ Program the device.
* Check the *Random* checkbox, and enter a *Min* and *Max* value, then select the **Set** button. Every time the sensor reads a value, it will read a random number between *Min* and *Max*.
The values you set will be output to in the console. Change the *Value* or the *Random* settings to make the value change.
The values you set will be output to the console. Change the *Value* or the *Random* settings to make the value change.
```output
(.venv) ➜ GroveTest python3 app.py

@ -198,7 +198,7 @@ Configure a Python virtual environment and install the MQTT pip packages.
source ./.venv/bin/activate
```
1. Once the virtual environment has been activated, the default `python` command will run the version of Python that was used to create the virtual environment. Run the following to get this version:
1. Once the virtual environment has been activated, the default `python` command will run the version of Python that was used to create the virtual environment. Run the following to get the version:
```sh
python --version

@ -132,6 +132,8 @@ The video below gives a short overview of Azure IoT Hub:
[![Overview of Azure IoT Hub video](https://img.youtube.com/vi/smuZaZZXKsU/0.jpg)](https://www.youtube.com/watch?v=smuZaZZXKsU)
> 🎥 Click the image above to watch a video
✅ Take a moment to do some research and read the overview of IoT hub in the [Microsoft IoT Hub documentation](https://docs.microsoft.com/azure/iot-hub/about-iot-hub?WT.mc_id=academic-17441-jabenn).
The cloud services available in Azure can be configured through a web-based portal, or via a command-line interface (CLI). For this task, you will use the CLI.

@ -46,7 +46,7 @@ Despite the name, serverless does actually use servers. The naming is because yo
As an IoT developer, the serverless model is ideal. You can write a function that is called in response to messages sent from any IoT device that is connected to your cloud-hosted IoT service. Your code will handle all messages sent, but only be running when needed.
✅ Look back at the code you wrote as server code listening to messages over MQTT. As is, how might this run in the cloud using serverless? How do you think the code might be changed to support serverless computing?
✅ Look back at the code you wrote as server code listening to messages over MQTT. How might this run in the cloud using serverless? How do you think the code might be changed to support serverless computing?
> 💁 The serverless model is moving to other cloud services in addition to running code. For example, serverless databases are available in the cloud using a serverless pricing model where you pay per request made against the database, such as a query or insert, usually using pricing based on how much work is done to service the request. For example a single select of one row against a primary key will cost less than a complicated operation joining many tables and returning thousands of rows.
@ -60,6 +60,8 @@ The short video below has an overview of Azure Functions
[![Azure Functions overview video](https://img.youtube.com/vi/8-jz5f_JyEQ/0.jpg)](https://www.youtube.com/watch?v=8-jz5f_JyEQ)
> 🎥 Click the image above to watch a video
✅ Take a moment to do some research and read the overview of Azure Functions in the [Microsoft Azure Functions documentation](https://docs.microsoft.com/azure/azure-functions/functions-overview?WT.mc_id=academic-17441-jabenn).
To write Azure Functions, you start with an Azure Functions app in the language of your choice. Out of the box Azure Functions supports Python, JavaScript, TypeScript, C#, F#, Java, and Powershell. In this lesson you will learn how to write an Azure Functions app in Python.
@ -192,6 +194,23 @@ The Azure Functions CLI can be used to create a new Functions app.
> ⚠️ If you get a firewall notification, grant access as the `func` application needs to be able to read and write to your network.
> ⚠️ If you are using macOS, there may be warnings in the output:
>
> ```output
> (.venv) ➜ soil-moisture-trigger func start
> Found Python version 3.9.1 (python3).
>
> Azure Functions Core Tools
> Core Tools Version: 3.0.3442 Commit hash: 6bfab24b2743f8421475d996402c398d2fe4a9e0 (64-bit)
> Function Runtime Version: 3.0.15417.0
>
> [2021-06-16T08:18:28.315Z] Cannot create directory for shared memory usage: /dev/shm/AzureFunctions
> [2021-06-16T08:18:28.316Z] System.IO.FileSystem: Access to the path '/dev/shm/AzureFunctions' is denied. Operation not permitted.
> [2021-06-16T08:18:30.361Z] No job functions found.
> ```
>
> You can ignore these as long as the Functions app starts correctly and lists the running functions. As mentioned in [this question on the Microsoft Docs Q&A](https://docs.microsoft.com/answers/questions/396617/azure-functions-core-tools-error-osx-devshmazurefu.html?WT.mc_id=academic-17441-jabenn) it can be ignored.
1. Stop the Functions app by pressing `ctrl+c`.
1. Open the current folder in VS Code, either by opening VS Code, then opening this folder, or by running the following:
@ -370,7 +389,7 @@ To connect to the Registry Manager, you need a connection string.
Replace `<hub_name>` with the name you used for your IoT Hub.
The connection string is requested for the *ServiceConnect* policy using the `--policy-name service` parameter. When you request a connection string, you can specify what permissions that connection string will allow. The ServiceConnect policy allows yor code to connect and send messages to IoT devices.
The connection string is requested for the *ServiceConnect* policy using the `--policy-name service` parameter. When you request a connection string, you can specify what permissions that connection string will allow. The ServiceConnect policy allows your code to connect and send messages to IoT devices.
✅ Do some research: Read up on the different policies in the [IoT Hub permissions documentation](https://docs.microsoft.com/azure/iot-hub/iot-hub-devguide-security#iot-hub-permissions?WT.mc_id=academic-17441-jabenn)

@ -39,7 +39,7 @@ If your IoT application is not secure, there are a number of risks:
These are real world scenarios, and happen all the time. Some examples were given in earlier lessons, but here are some more:
* In 2018 hackers used an open WiFi access point on a fish tank thermostat to gain access to a casino's network to steal data. [The Hacker News - Casino Gets Hacked Through Its Internet-Connected Fish Tank Thermometer](https://thehackernews.com/2018/04/iot-hacking-thermometer.html)
* In 2018, hackers used an open WiFi access point on a fish tank thermostat to gain access to a casino's network to steal data. [The Hacker News - Casino Gets Hacked Through Its Internet-Connected Fish Tank Thermometer](https://thehackernews.com/2018/04/iot-hacking-thermometer.html)
* In 2016, the Mirai Botnet launched a denial of service attack against Dyn, an Internet service provider, taking down large portions of the Internet. This botnet used malware to connect to IoT devices such as DVRs and cameras that used default usernames and passwords, and from there launched the attack. [The Guardian - DDoS attack that disrupted internet was largest of its kind in history, experts say](https://www.theguardian.com/technology/2016/oct/26/ddos-attack-dyn-mirai-botnet)
* Spiral Toys had a database of users of their CloudPets connected toys publicly available over the Internet. [Troy Hunt - Data from connected CloudPets teddy bears leaked and ransomed, exposing kids' voice messages](https://www.troyhunt.com/data-from-connected-cloudpets-teddy-bears-leaked-and-ransomed-exposing-kids-voice-messages/).
* Strava tagged runners that you ran past and showed their routes, allowing strangers to effectively see where you live. [Kim Komndo - Fitness app could lead a stranger right to your home — change this setting](https://www.komando.com/security-privacy/strava-fitness-app-privacy/755349/).
@ -90,7 +90,7 @@ Unfortunately, not everything is secure. Some devices have no security, others a
Encryption comes in two types - symmetric and asymmetric.
**Symmetric** encryption uses the same key to encrypt and decrypt the data. Both the sender and receive need to know the same key. This is the least secure type, as the key needs to be shared somehow. For a sender to send an encrypted message to a recipient, the sender first might have to send the recipient the key.
**Symmetric** encryption uses the same key to encrypt and decrypt the data. Both the sender and receiver need to know the same key. This is the least secure type, as the key needs to be shared somehow. For a sender to send an encrypted message to a recipient, the sender first might have to send the recipient the key.
![Symmetric key encryption uses the same key to encrypt and decrypt a message](../../../images/send-message-symmetric-key.png)
@ -148,7 +148,7 @@ After the connection, all data sent to the IoT Hub from the device, or to the de
### X.509 certificates
When you are using a asymmetric encryption with a public/private key pair, you need to provide your public key to anyone who wants to send you data. The problem is, how can the recipient of your key be sure it's actually your public key, not someone else pretending to be you? Instead of providing a key, you can instead provide your public key inside a certificate that has been verified by a trusted third party, called an X.509 certificate.
When you are using asymmetric encryption with a public/private key pair, you need to provide your public key to anyone who wants to send you data. The problem is, how can the recipient of your key be sure it's actually your public key, not someone else pretending to be you? Instead of providing a key, you can instead provide your public key inside a certificate that has been verified by a trusted third party, called an X.509 certificate.
X.509 certificates are digital documents that contain the public key part of the public/private key pair. They are usually issued by one of a number of trusted organizations called [Certification authorities](https://wikipedia.org/wiki/Certificate_authority) (CAs), and digitally signed by the CA to indicate the key is valid and comes from you. You trust the certificate and that the public key is from who the certificate says it is from, because you trust the CA, similar to how you would trust a passport or driving license because you trust the country issuing it. Certificates cost money, so you can also 'self-sign', that is create a certificate yourself that is signed by you, for testing purposes.
@ -162,7 +162,7 @@ When using X.509 certificates, both the sender and the recipient will have their
![Instead of sharing a public key, you can share a certificate. The user of the certificate can verify that it comes from you by checking with the certificate authority who signed it.](../../../images/send-message-certificate.png)
***nstead of sharing a public key, you can share a certificate. The user of the certificate can verify that it comes from you by checking with the certificate authority who signed it. Certificate by alimasykurm from the [Noun Project](https://thenounproject.com)***
***Instead of sharing a public key, you can share a certificate. The user of the certificate can verify that it comes from you by checking with the certificate authority who signed it. Certificate by alimasykurm from the [Noun Project](https://thenounproject.com)***
One big advantage of using X.509 certificates is that they can be shared between devices. You can create one certificate, upload it to IoT Hub, and use this for all your devices. Each device then just needs to know the private key to decrypt the messages it receives from IoT Hub.
@ -176,7 +176,7 @@ The certificate used by your device to encrypt messages it sends to the IoT Hub
The steps to generate an X.509 certificate are:
1. Create a public/private key pair. One of the most widely used algorithm to generate a public/private key pair is called [RSA](https://wikipedia.org/wiki/RSA_(cryptosystem)).
1. Create a public/private key pair. One of the most widely used algorithm to generate a public/private key pair is called [RivestShamirAdleman](https://wikipedia.org/wiki/RSA_(cryptosystem))(RSA).
1. Submit the public key with associated data for signing, either by a CA, or by self-signing

@ -47,8 +47,10 @@ The next step is to connect your device to IoT Hub using the X.509 certificates.
```
This will connect using the X.509 certificate instead of a connection string.
1. Delete the line with `connection_string` variable.
1, RUn your code. Monitor the messages sent to IoT Hub, and send direct method requests as before. You will see the device connecting and sending soil moisture readings, as well as receiving direct method requests.
1. Run your code. Monitor the messages sent to IoT Hub, and send direct method requests as before. You will see the device connecting and sending soil moisture readings, as well as receiving direct method requests.
> 💁 You can find this code in the [code/pi](code/pi) or [code/virtual-device](code/virtual-device) folder.

@ -1,10 +1,10 @@
# Transport from farm to factory - using IoT to track food deliveries
Many farmers grow food to sell - either they are commercial growers who sell everything they grow, or they are subsistence farmers who sell their excess produce to buy necessities. Somehow the food has to get from the farm to the consumer, and this usually relies on bulk transport from farms, to hubs or processing plants, then on to stores. For example, a tomato farmer will harvest tomatoes, pack them into boxes, load the boxes into a truck then deliver to a processing plant. The tomatoes will then be sorted, and from there delivered to the consumers in the form of retail, food processing, or restaurants.
Many farmers grow food to sell - either they are commercial farmers who sell everything they grow, or they are subsistence farmers who sell their excess produce to buy necessities. Somehow the food has to get from the farm to the consumer, and this usually relies on bulk transport from farms, to hubs or processing plants, then to stores. For example, a tomato farmer will harvest tomatoes, pack them into boxes, load the boxes into a truck then deliver to a processing plant. The tomatoes will then be sorted, and from there delivered to the consumers in the form of processed food, retail sales, or consumed at restaurants.
IoT can help with this supply chain by tracking the food in transit - ensuring drivers are going where they should, monitoring vehicle locations, and getting alerts when vehicles arrive so that food can be unloaded, ready for processing as soon as possible.
IoT can help with this supply chain by tracking the food in transit - ensuring drivers are going where they should, monitoring vehicle locations, and getting alerts when vehicles arrive so that food can be unloaded, and be ready for processing as soon as possible.
> 🎓 A *supply chain* is the sequence of activities to make and deliver something. For example, in tomato farming it covers seed, soil, fertilizer and water supply, growing tomatoes, delivering tomatoes to a central hub, transporting them to a supermarkets local hub, transporting to the individual supermarket, being put out on display, then sold to a consumer and taken home to eat. Each step is like the links in a chain.
> 🎓 A *supply chain* is the sequence of activities to make and deliver something. For example, in tomato farming it covers seed, soil, fertilizer and water supply, growing tomatoes, delivering tomatoes to a central hub, transporting them to a supermarket's local hub, transporting to the individual supermarket, being put out on display, then sold to a consumer and taken home to eat. Each step is like the links in a chain.
> 🎓 The transportation part of the supply chain is know as *logistics*.
@ -15,7 +15,7 @@ In these 4 lessons, you'll learn how to apply the Internet of Things to improve
## Topics
1. [Location tracking](lessons/1-location-tracking/README.md)
1. [Store location data](./3-transport/lessons/2-store-location-data/README.md)
1. [Store location data](lessons/2-store-location-data/README.md)
1. [Visualize location data](lessons/3-visualize-location-data/README.md)
1. [Geofences](lessons/4-geofences/README.md)

@ -10,13 +10,15 @@ Add a sketchnote if possible/appropriate
## Introduction
The main process for getting food from a farmer to a consumer involves loading boxes of produce on to trucks, ships, airplanes, or other commercial transport vehicles, and delivering the food somewhere - either direct to a customer, or to a central hub or warehouse for processing. The whole end-to-end process from farm to consumer is part of a process called the *supply chain*. The video below from Arizona State University's W. P. Carey School of Business talks about the idea of the supply chain and how it is managed in more detail.
The main process for getting food from a farmer to a consumer involves loading boxes of produce on to trucks, ships, airplanes, or other commercial transport vehicles, and delivering the food somewhere - either directly to a customer, or to a central hub or warehouse for processing. The whole end-to-end process from farm to consumer is part of a process called the *supply chain*. The video below from Arizona State University's W. P. Carey School of Business talks about the idea of the supply chain and how it is managed in more detail.
[![What is Supply Chain Management? A video from Arizona State University's W. P. Carey School of Business](https://img.youtube.com/vi/Mi1QBxVjZAw/0.jpg)](https://www.youtube.com/watch?v=Mi1QBxVjZAw)
> 🎥 Click the image above to watch a video
Adding IoT devices can drastically improve your supply chain, allowing you to manage where items are, plan transport and goods handling better, and respond quicker to problems.
When managing a fleet of vehicles such as trucks, it is helpful to know where each vehicle is at a given time. Vehicles can be fitted with GPS sensors that send their location to IoT systems, allowing the owners to pinpoint their location, see the route they have taken, and know when they will arrive at their destination. Most vehicles operate outside of WiFi coverage, so they use cellular networks to send this kind of data. Sometimes the GPS sensor is built into more complex IoT devices such as electronic log books. These devices track how long a truck has been driven for to ensure drivers are in compliance with local laws on working hours.
When managing a fleet of vehicles such as trucks, it is helpful to know where each vehicle is at a given time. Vehicles can be fitted with GPS sensors that send their location to IoT systems, allowing the owners to pinpoint their location, see the route they have taken, and know when they will arrive at their destination. Most vehicles operate outside of WiFi coverage, so they use cellular networks to send this kind of data. Sometimes the GPS sensor is built into more complex IoT devices such as electronic log books. These devices track how long a truck has been in transit to ensure drivers are in compliance with local laws on working hours.
In this lesson you will learn how to track a vehicles location using a Global Positioning System (GPS) sensor.
@ -53,11 +55,11 @@ The core component of vehicle tracking is GPS - sensors that can pinpoint their
## Geospatial coordinates
Geospatial coordinates are used to define points on the Earth's surface, similar to how coordinates can be used to draw to a pixel on a computer screen or position stitches in cross stitch. For a single point, you have a pair of coordinates. For example, the Microsoft Campus in Redmond, Washington, USA is located at 47.6423109,-122.1390293.
Geospatial coordinates are used to define points on the Earth's surface, similar to how coordinates can be used to draw to a pixel on a computer screen or position stitches in cross stitch. For a single point, you have a pair of coordinates. For example, the Microsoft Campus in Redmond, Washington, USA is located at 47.6423109, -122.1390293.
### Latitude and longitude
The Earth is a sphere - a three-dimensional circle. Because of this, points are defined is by dividing it into 360 degrees, the same as the geometry of circles. Latitude measures the number of degrees north to south, longitude measures the number of degrees east to west.
The Earth is a sphere - a three-dimensional circle. Because of this, points are defined by dividing it into 360 degrees, the same as the geometry of circles. Latitude measures the number of degrees north to south, longitude measures the number of degrees east to west.
> 💁 No-one really knows the original reason why circles are divided into 360 degrees. The [degree (angle) page on Wikipedia](https://wikipedia.org/wiki/Degree_(angle)) covers some of the possible reasons.
@ -178,7 +180,7 @@ Rather than use the raw NMEA data, it is better to decode it into a more useful
### Task - decode GPS sensor data
Work through the relevant guide to measure soil moisture using your IoT device:
Work through the relevant guide to decode GPS sensor data using your IoT device:
* [Arduino - Wio Terminal](wio-terminal-gps-decode.md)
* [Single-board computer - Raspberry Pi/Virtual IoT device](single-board-computer-gps-decode.md)

@ -6,7 +6,7 @@ The NMEA sentences that come from your GPS sensor have other data in addition to
For example - can you get the current date and time? If you are using a microcontroller, can you set the clock using GPS data in the same way you set is using NTP signals in the previous project? Can you get elevation (your height above sea level), or your current speed?
If you are using a virtual IoT device, then you can get some of this data by sending MENA sentences generated using tools [nmeagen.org](https://www.nmeagen.org).
If you are using a virtual IoT device, then you can get some of this data by sending NMEA sentences generated using tools [nmeagen.org](https://www.nmeagen.org).
## Rubric

@ -2,21 +2,12 @@ import time
import serial
import pynmea2
import json
from azure.iot.device import IoTHubDeviceClient, Message
connection_string = '<connection_string>'
serial = serial.Serial('/dev/ttyAMA0', 9600, timeout=1)
serial.reset_input_buffer()
serial.flush()
device_client = IoTHubDeviceClient.create_from_connection_string(connection_string)
print('Connecting')
device_client.connect()
print('Connected')
def printGPSData(line):
def print_gps_data(line):
msg = pynmea2.parse(line)
if msg.sentence_type == 'GGA':
lat = pynmea2.dm_to_sd(msg.lat)
@ -28,16 +19,13 @@ def printGPSData(line):
if msg.lon_dir == 'W':
lon = lon * -1
message_json = { "gps" : { "lat":lat, "lon":lon } }
print("Sending telemetry", message_json)
message = Message(json.dumps(message_json))
device_client.send_message(message)
print(f'{lat},{lon} - from {msg.num_sats} satellites')
while True:
line = serial.readline().decode('utf-8')
while len(line) > 0:
printGPSData(line)
print_gps_data(line)
line = serial.readline().decode('utf-8')
time.sleep(1)

@ -5,18 +5,11 @@ import time
import counterfit_shims_serial
import pynmea2
import json
from azure.iot.device import IoTHubDeviceClient, Message
connection_string = '<connection_string>'
serial = counterfit_shims_serial.Serial('/dev/ttyAMA0')
device_client = IoTHubDeviceClient.create_from_connection_string(connection_string)
print('Connecting')
device_client.connect()
print('Connected')
def send_gps_data(line):
msg = pynmea2.parse(line)
if msg.sentence_type == 'GGA':
@ -29,10 +22,7 @@ def send_gps_data(line):
if msg.lon_dir == 'W':
lon = lon * -1
message_json = { "gps" : { "lat":lat, "lon":lon } }
print("Sending telemetry", message_json)
message = Message(json.dumps(message_json))
device_client.send_message(message)
print(f'{lat},{lon} - from {msg.num_sats} satellites')
while True:
line = serial.readline().decode('utf-8')
@ -41,4 +31,4 @@ while True:
send_gps_data(line)
line = serial.readline().decode('utf-8')
time.sleep(60)
time.sleep(1)

@ -5,14 +5,14 @@ serial = serial.Serial('/dev/ttyAMA0', 9600, timeout=1)
serial.reset_input_buffer()
serial.flush()
def printGPSData():
def print_gps_data():
print(line.rstrip())
while True:
line = serial.readline().decode('utf-8')
while len(line) > 0:
printGPSData()
print_gps_data()
line = serial.readline().decode('utf-8')
time.sleep(1)

@ -6,14 +6,14 @@ import counterfit_shims_serial
serial = counterfit_shims_serial.Serial('/dev/ttyAMA0')
def printGPSData(line):
def print_gps_data(line):
print(line.rstrip())
while True:
line = serial.readline().decode('utf-8')
while len(line) > 0:
printGPSData(line)
print_gps_data(line)
line = serial.readline().decode('utf-8')
time.sleep(1)

@ -24,7 +24,7 @@ Connect the GPS sensor.
1. With the Raspberry Pi powered off, connect the other end of the Grove cable to the UART socket marked **UART** on the Grove Base hat attached to the Pi. This socket is on the middle row, on the side nearest the SD Card slot, the other end from the USB ports and ethernet socket.
![The grove GPS sensor connected to the UART socket](../../../images/pi-gps-sensor.png)
![The grove GPS sensor connected to the UART socket](../../../images/pi-gps-sensor.png)
1. Position the GPS sensor so that the attached antenna has visibility to the sky - ideally next to an open window or outside. It's easier to get a clearer signal with nothing in the way of the antenna.
@ -42,7 +42,7 @@ Program the device.
1. Launch VS Code, either directly on the Pi, or connect via the Remote SSH extension.
> ⚠️ You can refer to [the instructions for setting up and launch VS Code in lesson 1 if needed](../../../1-getting-started/lessons/1-introduction-to-iot/pi.md).
> ⚠️ You can refer to [the instructions for setting up and launching VS Code in lesson 1 if needed](../../../1-getting-started/lessons/1-introduction-to-iot/pi.md).
1. With newer versions of the Raspberry Pi that support Bluetooth, there is a conflict between the serial port used for Bluetooth, and the one used by the Grove UART port. To fix this, do the following:
@ -118,14 +118,14 @@ Program the device.
serial.reset_input_buffer()
serial.flush()
def printGPSData(line):
def print_gps_data(line):
print(line.rstrip())
while True:
line = serial.readline().decode('utf-8')
while len(line) > 0:
printGPSData(line)
print_gps_data(line)
line = serial.readline().decode('utf-8')
time.sleep(1)
@ -133,9 +133,9 @@ Program the device.
This code imports the `serial` module from the `pyserial` Pip package. It then connects to the `/dev/ttyAMA0` serial port - this is the address of the serial port that the Grove Pi Base Hat uses for its UART port. It then clears any existing data from this serial connection.
Next a function called `printGPSData` is defined that prints out the line passed to it to the console.
Next a function called `print_gps_data` is defined that prints out the line passed to it to the console.
Next the code loops forever, reading as many lines of text as it can from the serial port in each loop. It calls the `printGPSData` function for each line.
Next the code loops forever, reading as many lines of text as it can from the serial port in each loop. It calls the `print_gps_data` function for each line.
After all the data has been read, the loop sleeps for 1 second, then tries again.

@ -24,7 +24,7 @@ Program the device to decode the GPS data.
import pynmea2
```
1. Replace the contents of the `printGPSData` function with the following:
1. Replace the contents of the `print_gps_data` function with the following:
```python
msg = pynmea2.parse(line)

@ -77,28 +77,28 @@ Program the GPS sensor app.
1. Add the following code below this to read from the serial port and print the values to the console:
```python
def printGPSData(line):
def print_gps_data(line):
print(line.rstrip())
while True:
line = serial.readline().decode('utf-8')
while len(line) > 0:
printGPSData(line)
print_gps_data(line)
line = serial.readline().decode('utf-8')
time.sleep(1)
```
A function called `printGPSData` is defined that prints out the line passed to it to the console.
A function called `print_gps_data` is defined that prints out the line passed to it to the console.
Next the code loops forever, reading as many lines of text as it can from the serial port in each loop. It calls the `printGPSData` function for each line.
Next the code loops forever, reading as many lines of text as it can from the serial port in each loop. It calls the `print_gps_data` function for each line.
After all the data has been read, the loop sleeps for 1 second, then tries again.
1. Run this code, ensuring you are using a different terminal to the one that the CounterFit app is running it, so that the CounterFit app remains running.
1. From the CounterFit app, change the value of the gps sensor. You can do this in one of thess ways:
1. From the CounterFit app, change the value of the gps sensor. You can do this in one of these ways:
* Set the **Source** to `Lat/Lon`, and set an explicit latitude, longitude and number of satellites used to get the GPS fix. This value will be sent only once, so check the **Repeat** box to have the data repeat every second.

@ -31,7 +31,7 @@ Program the device to decode the GPS data.
TinyGPSPlus gps;
```
1. Change the contents of the `printGPSData` function to be the following:
1. Change the contents of the `printGPSData` function to the following:
```cpp
if (gps.encode(Serial3.read()))

@ -22,15 +22,15 @@ Connect the GPS sensor.
1. Insert one end of a Grove cable into the socket on the GPS sensor. It will only go in one way round.
1. With the Wio Terminal disconnected from your computer or other power supply, connect the other end of the Grove cable to the left-hand side Grove socket on the Wio Terminal as you look at the screen. This is the socket closest to from the power button.
1. With the Wio Terminal disconnected from your computer or other power supply, connect the other end of the Grove cable to the left-hand side Grove socket on the Wio Terminal as you look at the screen. This is the socket closest to the power button.
![The grove GPS sensor connected to the left hand socket](../../../images/wio-gps-sensor.png)
![The grove GPS sensor connected to the left hand socket](../../../images/wio-gps-sensor.png)
1. Position the GPS sensor so that the attached antenna has visibility to the sky - ideally next to an open window or outside. It's easier to get a clearer signal with nothing in the way of the antenna.
1. You can now connect the Wio Terminal to your computer.
1. The GPS sensor has 2 LEDs - a blue LED that flashes when data is transmitted, and a green LED that flashes every second when receiving data from satellites. Ensure the blue LED is flashing when you power up the Pi. After a few minutes the green LED will flash - if not, you may need to reposition the antenna.
1. The GPS sensor has 2 LEDs - a blue LED that flashes when data is transmitted, and a green LED that flashes every second when receiving data from satellites. Ensure the blue LED is flashing when you power up the Wio Terminal. After a few minutes the green LED will flash - if not, you may need to reposition the antenna.
## Program the GPS sensor

@ -264,7 +264,7 @@ The data will be saved as a JSON blob with the following format:
import json
import os
import uuid
from azure.storage.blob import BlobServiceClient
from azure.storage.blob import BlobServiceClient, PublicAccess
```
The `json` system module will be used to read and write JSON, the `os` system module will be used to read the connection string, the `uuid` system module will be used to generate a unique ID for the GPS reading.
@ -282,11 +282,13 @@ The data will be saved as a JSON blob with the following format:
if container.name == name:
return blob_service_client.get_container_client(container.name)
return blob_service_client.create_container(name)
return blob_service_client.create_container(name, public_access=PublicAccess.Container)
```
The Python blob SDK doesn't have a helper method to create a container if it doesn't exist. This code will load the connection string from the `local.settings.json` file (or the Application Settings once deployed to the cloud), then create a `BlobServiceClient` class from this to interact with the blob storage account. It then loops through all the containers for the blob storage account, looking for one with the provided name - if it finds one it will return a `ContainerClient` class that can interact with the container to create blobs. If it doesn't find one, then the container is created and the client for the new container is returned.
When the new container is created, public access is granted to query the blobs in the container. This will be used in the next lesson to visualize the GPS data on a map.
1. Unlike with soil moisture, with this code we want to store every event, so add the following code inside the `for event in events:` loop in the `main` function, below the `logging` statement:
```python
@ -294,7 +296,7 @@ The data will be saved as a JSON blob with the following format:
blob_name = f'{device_id}/{str(uuid.uuid1())}.json'
```
This code gets the device ID from the event metadata, then uses it to create a blob name. Blobs can be stored in folders, and device ID will be used for the folder name, so each device will have all it's GPS events in one folder. The blob name is this folder, followed by a document name, separated with forward slashes, similar to Linux and macOS paths (similar to Windows as well, but Windows uses back slashes). The document name is a unique ID generated using the Python `uuid` module, with the file type of `json`.
This code gets the device ID from the event metadata, then uses it to create a blob name. Blobs can be stored in folders, and device ID will be used for the folder name, so each device will have all its GPS events in one folder. The blob name is this folder, followed by a document name, separated with forward slashes, similar to Linux and macOS paths (similar to Windows as well, but Windows uses back slashes). The document name is a unique ID generated using the Python `uuid` module, with the file type of `json`.
For example, for the `gps-sensor` device ID, the blob name might be `gps-sensor/a9487ac2-b9cf-11eb-b5cd-1e00621e3648.json`.

@ -5,7 +5,7 @@ import azure.functions as func
import json
import os
import uuid
from azure.storage.blob import BlobServiceClient
from azure.storage.blob import BlobServiceClient, PublicAccess
def get_or_create_container(name):
connection_str = os.environ['STORAGE_CONNECTION_STRING']
@ -15,7 +15,7 @@ def get_or_create_container(name):
if container.name == name:
return blob_service_client.get_container_client(container.name)
return blob_service_client.create_container(name)
return blob_service_client.create_container(name, public_access=PublicAccess.Container)
def main(events: List[func.EventHubEvent]):
for event in events:

@ -1,13 +1,14 @@
import time
from grove.adc import ADC
from grove.grove_relay import GroveRelay
import serial
import pynmea2
import json
from azure.iot.device import IoTHubDeviceClient, Message, MethodResponse
from azure.iot.device import IoTHubDeviceClient, Message
connection_string = '<connection_string>'
adc = ADC()
relay = GroveRelay(5)
serial = serial.Serial('/dev/ttyAMA0', 9600, timeout=1)
serial.reset_input_buffer()
serial.flush()
device_client = IoTHubDeviceClient.create_from_connection_string(connection_string)
@ -15,24 +16,28 @@ print('Connecting')
device_client.connect()
print('Connected')
def handle_method_request(request):
print("Direct method received - ", request.name)
if request.name == "relay_on":
relay.on()
elif request.name == "relay_off":
relay.off()
def print_gps_data(line):
msg = pynmea2.parse(line)
if msg.sentence_type == 'GGA':
lat = pynmea2.dm_to_sd(msg.lat)
lon = pynmea2.dm_to_sd(msg.lon)
method_response = MethodResponse.create_from_method_request(request, 200)
device_client.send_method_response(method_response)
if msg.lat_dir == 'S':
lat = lat * -1
device_client.on_method_request_received = handle_method_request
if msg.lon_dir == 'W':
lon = lon * -1
message_json = { "gps" : { "lat":lat, "lon":lon } }
print("Sending telemetry", message_json)
message = Message(json.dumps(message_json))
device_client.send_message(message)
while True:
soil_moisture = adc.read(0)
print("Soil moisture:", soil_moisture)
line = serial.readline().decode('utf-8')
message = Message(json.dumps({ 'soil_moisture': soil_moisture }))
device_client.send_message(message)
while len(line) > 0:
print_gps_data(line)
line = serial.readline().decode('utf-8')
time.sleep(10)
time.sleep(60)

@ -2,15 +2,14 @@ from counterfit_connection import CounterFitConnection
CounterFitConnection.init('127.0.0.1', 5000)
import time
from counterfit_shims_grove.adc import ADC
from counterfit_shims_grove.grove_relay import GroveRelay
import counterfit_shims_serial
import pynmea2
import json
from azure.iot.device import IoTHubDeviceClient, Message, MethodResponse
from azure.iot.device import IoTHubDeviceClient, Message
connection_string = '<connection_string>'
adc = ADC()
relay = GroveRelay(5)
serial = counterfit_shims_serial.Serial('/dev/ttyAMA0')
device_client = IoTHubDeviceClient.create_from_connection_string(connection_string)
@ -18,24 +17,28 @@ print('Connecting')
device_client.connect()
print('Connected')
def handle_method_request(request):
print("Direct method received - ", request.name)
if request.name == "relay_on":
relay.on()
elif request.name == "relay_off":
relay.off()
def send_gps_data(line):
msg = pynmea2.parse(line)
if msg.sentence_type == 'GGA':
lat = pynmea2.dm_to_sd(msg.lat)
lon = pynmea2.dm_to_sd(msg.lon)
method_response = MethodResponse.create_from_method_request(request, 200)
device_client.send_method_response(method_response)
if msg.lat_dir == 'S':
lat = lat * -1
device_client.on_method_request_received = handle_method_request
if msg.lon_dir == 'W':
lon = lon * -1
message_json = { "gps" : { "lat":lat, "lon":lon } }
print("Sending telemetry", message_json)
message = Message(json.dumps(message_json))
device_client.send_message(message)
while True:
soil_moisture = adc.read(0)
print("Soil moisture:", soil_moisture)
line = serial.readline().decode('utf-8')
message = Message(json.dumps({ 'soil_moisture': soil_moisture }))
device_client.send_message(message)
while len(line) > 0:
send_gps_data(line)
line = serial.readline().decode('utf-8')
time.sleep(10)
time.sleep(60)

@ -1,27 +1,168 @@
# Visualize location data
Add a sketchnote if possible/appropriate
![Embed a video here if available](video-url)
## Pre-lecture quiz
[Pre-lecture quiz](https://brave-island-0b7c7f50f.azurestaticapps.net/quiz/25)
## Introduction
In this lesson you will learn about
In the last lesson you learned how to get GPS data from your sensors to save to the cloud in a storage container using serverless code. Now you will discover how to visualize those points on an Azure map.
In this lesson we'll cover:
* [Thing 1](#thing-1)
- [What is Azure maps?](#what-is-azure-maps)
- [Create an Azure Maps resource](#create-an-azure-maps-resource)
- [Show a map on a web page](#show-a-map-on-a-web-page)
- [The GeoJSON format](#the-geojson-format)
- [Plot GPS data on a Map using GeoJSON](#plot-gps-data-on-a-map-using-geojson)
## What is Azure maps?
Working with maps is an interesting exercise, and there are many to choose from such as Bing Maps, Leaflet, Open Street Maps, and Google Maps. In this lesson, you will learn about [Azure Maps](https://azure.microsoft.com/services/azure-maps/#azuremaps-overview?WT.mc_id=academic-17441-jabenn) and how they can display your GPS data.
✅ Check out [this video](https://sec.ch9.ms/ch9/d498/3d435d2c-ac85-421b-b3a7-5e0c7630d498/IoT_AzureMaps_high.mp4) on using Azure Maps with IoT.
Azure Maps is "a collection of geospatial services and SDKs that use fresh mapping data to provide geographic context to web and mobile applications." Developers are provided with tools to create beautiful, interactive maps that can do things like provide recommended traffic routes, give information about traffic incidents, indoor navigation, search capabilities, elevation information, weather services and more.
> ✅ Experiment with some [mapping code samples](https://docs.microsoft.com/samples/browse/?products=azure-maps?WT.mc_id=academic-17441-jabenn)
You can display the maps as a blank canvas, tiles, satellite images, satellite images with roads superimposed, various types of grayscale maps, maps with shaded relief to show elevation, night view maps, and a high contrast map. You can get real-time updates on your maps by integrating them with [Azure Event Grid](https://azure.microsoft.com/services/event-grid/?WT.mc_id=academic-17441-jabenn). You can control the behavior and look of your maps by enabling various controls to allow the map to react to events like pinch, drag, and click. To control the look of your map, you can add layers that include bubbles, lines, polygons, heat maps, and more. Which style of map you implement depends on your choice of SDK.
You can access Azure Maps APIs by leveraging its [REST API](https://docs.microsoft.com/javascript/api/azure-maps-rest/?view=azure-maps-typescript-latest?WT.mc_id=academic-17441-jabenn), its [Web SDK](https://docs.microsoft.com/azure/azure-maps/how-to-use-map-control?WT.mc_id=academic-17441-jabenn), or, if you are building a mobile app, its [Android SDK](https://docs.microsoft.com/azure/azure-maps/how-to-use-android-map-control-library?pivots=programming-language-java-android?WT.mc_id=academic-17441-jabenn).
In this lesson, you will use the web SDK to draw a map and display your sensor's GPS location's path.
## Create an Azure Maps resource
Your first step is to create an Azure Maps account. The easiest way to do this is in the [Azure portal](https://portal.azure.com?WT.mc_id=academic-17441-jabenn).
1. After logging in to the portal, click the "Create a resource" button and in the search box that appears, type "Azure Maps".
1. Select "Azure Maps" and click 'Create'.
1. On the Create Azure Maps Account page, enter:
- Your subscription in the dropdown box.
- A Resource group to use (use 'gps-sensor' as you have done throughout these lessons)
- Add a name for your account
- Choose a Pricing tier. The Pricing tier for this account. S0 will work for this small project.
1. Read and accept the terms of service, and click the 'Create' button.
1. The service will deploy and you can visit it by clicking 'Go to resource' in the next screen.
2. Navigate to your new Azure Maps Account Authentication screen. Here, you discover that you have two ways to authenticate your maps in a web app: using Active Directory (AD) or 'Shared Key Authentication', also known as Subscription Key. We'll use the latter, for simplicity. Copy the Primary Key value and make a note of it!
✅ You will be able to rotate and swap keys at will using the Shared Keys; switch your app to use the Secondary Key while rotating the Primary Key if needed.
## Show a map on a web page
Now you can take the next step which is to display your map on a web page. We will use just one .html file for your small web app; keep in mind that in a production or team environment, your web app will most likely have more moving parts!
1. Create a file called index.html in a folder somewhere on your local computer. Add HTML markup to hold a map:
```html
<html>
<head>
<style>
#myMap {
width:100%;
height:100%;
}
</style>
</head>
## Thing 1
<body onload="init()">
<div id="myMap"></div>
</body>
</html>
```
The map will load in the 'myMap' `div`. A few styles allow it so span the width and height of the page.
2. Under the opening `<head>` tag, add an external style sheet to control the map display, and an external script from the Web SDK to manage its behavior:
```
<link rel="stylesheet" href="https://atlas.microsoft.com/sdk/javascript/mapcontrol/2/atlas.min.css" type="text/css" />
<script src="https://atlas.microsoft.com/sdk/javascript/mapcontrol/2/atlas.min.js"></script>
```
3. Under that script, add a script block to launch the map. Add your own subscriptionKey in the init() function:
```javascript
<script type='text/javascript'>
function init() {
var map = new atlas.Map('myMap', {
center: [-122.33, 47.6],
zoom: 12,
authOptions: {
authType: "subscriptionKey",
subscriptionKey: "<your-key-here>",
}
});
}
</script>
```
If you open your index.html page in a web browser, you should see a map loaded, and focused on Seattle:
![map image](images/map-image.png)
✅ Experiment with the zoom and center parameters to change your map display.
> A better way to work with web apps locally is to install [http-server](https://www.npmjs.com/package/http-server). You will need [node.js](https://nodejs.org/) and [npm](https://www.npmjs.com/) installed before using this tool. Once those tools are installed, you can navigate to the location of your `index.html` file and type `http-server`. The web app will open on a local webserver http://127.0.0.1:8080/.
## The GeoJSON format
Now that you have your web app in place with the map displaying, you need to extract GPS data from your storage and display it in a layer of markers on top of the map. Before we do that, let's look at the [GeoJSON](https://wikipedia.org/wiki/GeoJSON) format that is required by Azure Maps.
[GeoJSON](https://geojson.org/) is an open standard JSON specification with special formatting designed to handle geographic-specific data. You can learn about it by testing sample data using [geojson.io](geojson.io), which is also a useful tool to debug GeoJSON files.
Sample GeoJSON data looks like this:
```json
{
"type": "FeatureCollection",
"features": [
{
"type": "Feature",
"geometry": {
"type": "Point",
"coordinates": [
-2.10237979888916,
57.164918677004714
]
}
}
]
}
```
Of particular interest is the way the data is nested as a 'FeatureCollection'. Within that object can be found 'geometry' with the 'coordinates' indicating latitude and longitude. Geometry can have different 'types' designated to that a polygon could be drawn to a map; in this case, a point is drawn with two coordinates designated.
✅ Azure Maps supports standard GeoJSON plus some [enhanced features](https://docs.microsoft.com/azure/azure-maps/extend-geojson?WT.mc_id=academic-17441-jabenn) including the ability to draw circles and other geometries.
## Plot GPS data on a Map using GeoJSON
Now you are ready to consume data from the storage that you built in the previous lesson. As a reminder, it is stored as a number of files in blob storage so you will need to retrieve the files and parse them so that Azure Maps can use the data.
If you make a call to your storage to fetch the data you might be surprised to see errors occurring in your browser's console. That's because you need to set permissions for [CORS](https://developer.mozilla.org/docs/Web/HTTP/CORS) on this storage to allow external web apps to read its data. CORS stands for "Cross-Origin Resource Sharing" and usually needs to be set explicitly in Azure for security reasons. Do this using the Azure CLI, adding the name of your storage container and its key. We only need to 'GET' data from this container:
```dotnetcli
az storage cors add --methods GET \
--origins "*" \
--services b \
--account-name <storage_name> \
--account-key <key1>
```
TODO - fetch call explanation
---
## 🚀 Challenge
It's nice to be able to display static data on a map as markers. Can you enhance this web app to add animation and show the path of the markers over time, using the timestamped json files? Here are some samples of using animation
## Post-lecture quiz
[Post-lecture quiz](https://brave-island-0b7c7f50f.azurestaticapps.net/quiz/26)
@ -30,4 +171,4 @@ In this lesson we'll cover:
## Assignment
[](assignment.md)
[Deploy your app](assignment.md)

@ -1,9 +1,12 @@
#
# Deploy your app
## Instructions
There are several ways that you can deploy your app so that you can share it with the world, including using GitHub pages or using one of many service providers. A really excellent way to do this is to use Azure Static Web Apps. In this assignment, build your web app and deploy it to the cloud by following [these instructions](https://github.com/Azure/static-web-apps-cli) or watching [these videos](https://www.youtube.com/watch?v=ADVGIXciYn8&list=PLlrxD0HtieHgMPeBaDQFx9yNuFxx6S1VG&index=3).
A benefit of using Azure Static Web Apps is that you can hide any API keys in the portal, so take this opportunity to refactor your subscriptionKey as a variable and store it in the cloud.
## Rubric
| Criteria | Exemplary | Adequate | Needs Improvement |
| -------- | --------- | -------- | ----------------- |
| | | | |
| Criteria | Exemplary | Adequate | Needs Improvement |
| -------- | --------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------- | --------------------------------------------------- |
| | A working web app is presented in a documented GitHub repository with its subscriptionKey stored in the cloud and called via a variable | A working web app is presented in a documented GitHub repository but its subscriptionKey is not stored in the cloud | The web app contains bugs or does not work properly |

@ -0,0 +1,46 @@
<html>
<head>
<link rel="stylesheet" href="https://atlas.microsoft.com/sdk/javascript/mapcontrol/2/atlas.min.css" type="text/css" />
<script src="https://atlas.microsoft.com/sdk/javascript/mapcontrol/2/atlas.min.js"></script>
<script type='text/javascript'>
function init() {
fetch("https://gpssensorjimb.blob.core.windows.net/gps-data/?restype=container&comp=list")
.then(response => response.text())
.then(str => new window.DOMParser().parseFromString(str, "text/xml"))
.then(xml => {
let blobList = Array.from(xml.querySelectorAll("Url")); //.getAttribute("Url");
blobList.forEach(async blobUrl => {
console.log(blobUrl);
});
})
.then( response => {
var map = new atlas.Map('myMap', {
center: [-122.33, 47.6],
zoom: 12,
authOptions: {
authType: "subscriptionKey",
subscriptionKey: "<your-key>",
}
});
})
}
</script>
<style>
#myMap {
width:100%;
height:100%;
}
</style>
</head>
<body onload="init()">
<div id="myMap"></div>
</body>
</html>

Binary file not shown.

After

Width:  |  Height:  |  Size: 571 KiB

@ -6,6 +6,8 @@ This video gives an overview of geofences and how to use them in Azure Maps, top
[![Geofencing with Azure Maps from the Microsoft Developer IoT show](https://img.youtube.com/vi/nsrgYhaYNVY/0.jpg)](https://www.youtube.com/watch?v=nsrgYhaYNVY)
> 🎥 Click the image above to watch a video
## Pre-lecture quiz
[Pre-lecture quiz](https://brave-island-0b7c7f50f.azurestaticapps.net/quiz/27)

@ -6,6 +6,8 @@ This video gives an overview of the Azure Custom Vision service, a service that
[![Custom Vision Machine Learning Made Easy | The Xamarin Show](https://img.youtube.com/vi/TETcDLJlWR4/0.jpg)](https://www.youtube.com/watch?v=TETcDLJlWR4)
> 🎥 Click the image above to watch a video
## Pre-lecture quiz
[Pre-lecture quiz](https://brave-island-0b7c7f50f.azurestaticapps.net/quiz/29)
@ -44,6 +46,8 @@ The video below shows one of these machines in action.
[![Automatic sorting of tomatoes via color](https://img.youtube.com/vi/AcRL91DouAU/0.jpg)](https://www.youtube.com/watch?v=AcRL91DouAU)
> 🎥 Click the image above to watch a video
In this video, as tomatoes fall from one conveyer belt to another, green tomatoes are detected and flicked into a bin using levers.
✅ What conditions would you need in a factory or in a field for these optical sensors to work correctly?

@ -6,6 +6,8 @@ This video gives an overview of running image classifiers on IoT devices, the to
[![Custom Vison AI on Azure IoT Edge](https://img.youtube.com/vi/_K5fqGLO8us/0.jpg)](https://www.youtube.com/watch?v=_K5fqGLO8us)
> 🎥 Click the image above to watch a video
## Pre-lecture quiz
[Pre-lecture quiz](https://brave-island-0b7c7f50f.azurestaticapps.net/quiz/33)

@ -1,7 +1,20 @@
# Retail - using IoT to manage stock levels
The last stage for feed before it reaches consumers is retail - the markets, greengrocers, supermarkets and stores that sell produce to consumers. These stores want to ensure they have produce out on shelves for consumers to see and buy.
One of the most manual, time consuming tasks in food stores, especially in large supermarkets, is making sure the shelves are stocked. Checking individual shelves to ensure any gaps are filled with produce from store rooms.
IoT can help with this, using AI models running on IoT devices to count stock, using machine learning models that don't just classify images, but can detect individual objects and count them.
In these 2 lessons you'll learn how to train image-based AI models to count stock, and run these models on IoT devices.
> 💁 These lessons will use some cloud resources. If you don't complete all the lessons in this project, make sure you [Clean up your project](../clean-up.md).
## Topics
1. [Train a stock detector](./lessons/1-train-stock-detector/README.md)
1. [Check stock from an IoT device](./lessons/2-check-stock-device/README.md)
## Credits
All the lessons were written with ♥️ by [Jim Bennett](https://GitHub.com/JimBobBennett)

@ -0,0 +1,33 @@
# Train a stock detector
Add a sketchnote if possible/appropriate
![Embed a video here if available](video-url)
## Pre-lecture quiz
[Pre-lecture quiz](https://brave-island-0b7c7f50f.azurestaticapps.net/quiz/37)
## Introduction
In this lesson you will learn about
In this lesson we'll cover:
* [Thing 1](#thing-1)
## Thing 1
---
## 🚀 Challenge
## Post-lecture quiz
[Post-lecture quiz](https://brave-island-0b7c7f50f.azurestaticapps.net/quiz/38)
## Review & Self Study
## Assignment
[](assignment.md)

@ -0,0 +1,9 @@
#
## Instructions
## Rubric
| Criteria | Exemplary | Adequate | Needs Improvement |
| -------- | --------- | -------- | ----------------- |
| | | | |

@ -0,0 +1,33 @@
# Check stock from an IoT device
Add a sketchnote if possible/appropriate
![Embed a video here if available](video-url)
## Pre-lecture quiz
[Pre-lecture quiz](https://brave-island-0b7c7f50f.azurestaticapps.net/quiz/39)
## Introduction
In this lesson you will learn about
In this lesson we'll cover:
* [Thing 1](#thing-1)
## Thing 1
---
## 🚀 Challenge
## Post-lecture quiz
[Post-lecture quiz](https://brave-island-0b7c7f50f.azurestaticapps.net/quiz/40)
## Review & Self Study
## Assignment
[](assignment.md)

@ -0,0 +1,9 @@
#
## Instructions
## Rubric
| Criteria | Exemplary | Adequate | Needs Improvement |
| -------- | --------- | -------- | ----------------- |
| | | | |

@ -0,0 +1,9 @@
# Dummy File
This file acts as a placeholder for the `translations` folder. <br>
**Please remove this file after adding the first translation**
For the instructions, follow the directives in the [translations guide](https://github.com/microsoft/IoT-For-Beginners/blob/main/TRANSLATIONS.md) .
## THANK YOU
We truly appreciate your efforts!

@ -6,9 +6,11 @@ This video gives an overview of the Azure speech service, a topic that will be c
[![How to get started using your Cognitive Services Speech resource from the Microsoft Azure YouTube channel](https://img.youtube.com/vi/iW0Fw0l3mrA/0.jpg)](https://www.youtube.com/watch?v=iW0Fw0l3mrA)
> 🎥 Click the image above to watch a video
## Pre-lecture quiz
[Pre-lecture quiz](https://brave-island-0b7c7f50f.azurestaticapps.net/quiz/33)
[Pre-lecture quiz](https://brave-island-0b7c7f50f.azurestaticapps.net/quiz/41)
## Introduction
@ -145,7 +147,9 @@ To avoid the complexity of training and using a wake word model, the smart timer
## Convert speech to text
Just like with image classification in the last project, there are pre-built AI services that can take speech as an audio file and convert it to text. Once such service is the Speech Service, part of the Cognitive Services, pre-built AI services you can use in your apps.
![Speech services logo](../../../images/azure-speech-logo.png)
Just like with image classification in an earlier project, there are pre-built AI services that can take speech as an audio file and convert it to text. Once such service is the Speech Service, part of the Cognitive Services, pre-built AI services you can use in your apps.
### Task - configure a speech AI resource
@ -212,7 +216,7 @@ What do you think the future holds for speech recognition?
## Post-lecture quiz
[Post-lecture quiz](https://brave-island-0b7c7f50f.azurestaticapps.net/quiz/34)
[Post-lecture quiz](https://brave-island-0b7c7f50f.azurestaticapps.net/quiz/42)
## Review & Self Study

@ -41,7 +41,7 @@ def capture_audio():
return wav_buffer
api_key = '<key>'
speech_api_key = '<key>'
location = '<location>'
language = '<language>'
connection_string = '<connection_string>'
@ -54,7 +54,7 @@ print('Connected')
def get_access_token():
headers = {
'Ocp-Apim-Subscription-Key': api_key
'Ocp-Apim-Subscription-Key': speech_api_key
}
token_endpoint = f'https://{location}.api.cognitive.microsoft.com/sts/v1.0/issuetoken'

@ -3,7 +3,7 @@ import time
from azure.cognitiveservices.speech import SpeechConfig, SpeechRecognizer
from azure.iot.device import IoTHubDeviceClient, Message
api_key = '<key>'
speech_api_key = '<key>'
location = '<location>'
language = '<language>'
connection_string = '<connection_string>'
@ -14,11 +14,11 @@ print('Connecting')
device_client.connect()
print('Connected')
speech_config = SpeechConfig(subscription=api_key,
region=location,
speech_recognition_language=language)
recognizer_config = SpeechConfig(subscription=speech_api_key,
region=location,
speech_recognition_language=language)
recognizer = SpeechRecognizer(speech_config=speech_config)
recognizer = SpeechRecognizer(speech_config=recognizer_config)
def recognized(args):
if len(args.result.text) > 0:

@ -39,13 +39,13 @@ def capture_audio():
return wav_buffer
api_key = '<key>'
speech_api_key = '<key>'
location = '<location>'
language = '<language>'
def get_access_token():
headers = {
'Ocp-Apim-Subscription-Key': api_key
'Ocp-Apim-Subscription-Key': speech_api_key
}
token_endpoint = f'https://{location}.api.cognitive.microsoft.com/sts/v1.0/issuetoken'

@ -1,15 +1,15 @@
import time
from azure.cognitiveservices.speech import SpeechConfig, SpeechRecognizer
api_key = '<key>'
speech_api_key = '<key>'
location = '<location>'
language = '<language>'
speech_config = SpeechConfig(subscription=api_key,
region=location,
speech_recognition_language=language)
recognizer_config = SpeechConfig(subscription=speech_api_key,
region=location,
speech_recognition_language=language)
recognizer = SpeechRecognizer(speech_config=speech_config)
recognizer = SpeechRecognizer(speech_config=recognizer_config)
def recognized(args):
print(args.result.text)

@ -22,12 +22,12 @@ The audio can be sent to the speech service using the REST API. To use the speec
1. Add the following code above the `while True` loop to declare some settings for the speech service:
```python
api_key = '<key>'
speech_api_key = '<key>'
location = '<location>'
language = '<language>'
```
Replace `<key>` with the API key for your speech service. Replace `<location>` with the location you used when you created the speech service resource.
Replace `<key>` with the API key for your speech service resource. Replace `<location>` with the location you used when you created the speech service resource.
Replace `<language>` with the locale name for language you will be speaking in, for example `en-GB` for English, or `zn-HK` for Cantonese. You can find a list of the supported languages and their locale names in the [Language and voice support documentation on Microsoft docs](https://docs.microsoft.com/azure/cognitive-services/speech-service/language-support?WT.mc_id=academic-17441-jabenn#speech-to-text).
@ -36,7 +36,7 @@ The audio can be sent to the speech service using the REST API. To use the speec
```python
def get_access_token():
headers = {
'Ocp-Apim-Subscription-Key': api_key
'Ocp-Apim-Subscription-Key': speech_api_key
}
token_endpoint = f'https://{location}.api.cognitive.microsoft.com/sts/v1.0/issuetoken'

@ -41,13 +41,13 @@ On Windows, Linux, and macOS, the speech services Python SDK can be used to list
1. Add the following code to declare some configuration:
```python
api_key = '<key>'
speech_api_key = '<key>'
location = '<location>'
language = '<language>'
speech_config = SpeechConfig(subscription=api_key,
region=location,
speech_recognition_language=language)
recognizer_config = SpeechConfig(subscription=speech_api_key,
region=location,
speech_recognition_language=language)
```
Replace `<key>` with the API key for your speech service. Replace `<location>` with the location you used when you created the speech service resource.
@ -59,7 +59,7 @@ On Windows, Linux, and macOS, the speech services Python SDK can be used to list
1. Add the following code to create a speech recognizer:
```python
recognizer = SpeechRecognizer(speech_config=speech_config)
recognizer = SpeechRecognizer(speech_config=recognizer_config)
```
1. The speech recognizer runs on a background thread, listening for audio and converting any speech in it to text. You can get the text using a callback function - a function you define and pass to the recognizer. Every time speech is detected, the callback is called. Add the following code to define a callback that prints the text to the console, and pass this callback to the recognizer:

@ -6,7 +6,7 @@ Add a sketchnote if possible/appropriate
## Pre-lecture quiz
[Pre-lecture quiz](https://brave-island-0b7c7f50f.azurestaticapps.net/quiz/33)
[Pre-lecture quiz](https://brave-island-0b7c7f50f.azurestaticapps.net/quiz/43)
## Introduction
@ -155,14 +155,18 @@ You can find instructions for using the LUIS portal in the [Quickstart: Build yo
* `set a 1 second timer`
* `set a 4 minute timer`
* `set a four minute six second timer`
* `set a 9 minute 30 second timer`
* `set a timer for 1 minute and 12 seconds`
* `set a timer for 3 minutes`
* `set a timer for 3 minutes and 1 second`
* `set a timer for 1 minute1 and 1 second`
* `set a timer for three minutes and one second`
* `set a timer for 1 minute and 1 second`
* `set a timer for 30 seconds`
* `set a timer for 1 second`
Mix up numbers as words and numerics so the model learns to handle both.
1. As you enter each example, LUIS will start detecting entities, and will underline and label any it finds.
![The examples with the numbers and time units underlined by LUIS](../../../images/luis-intent-examples.png)
@ -343,7 +347,7 @@ Once published, the LUIS model can be called from code. In the last lesson you s
if prediction_response.prediction.top_intent == 'set timer':
numbers = prediction_response.prediction.entities['number']
time_units = prediction_response.prediction.entities['time unit']
total_time = 0
total_seconds = 0
```
The `number` entities wil be an array of numbers. For example, if you said *"Set a four minute 17 second timer."*, then the `number` array will contain 2 integers - 4 and 17.
@ -388,15 +392,15 @@ Once published, the LUIS model can be called from code. In the last lesson you s
```python
if time_unit == 'minute':
total_time += number * 60
total_seconds += number * 60
else:
total_time += number
total_seconds += number
```
1. Finally, outside this loop through the entities, log the total time for the timer:
```python
logging.info(f'Timer required for {total_time} seconds')
logging.info(f'Timer required for {total_seconds} seconds')
```
1. Run the function app and speak into your IoT device. You will see the total time for the timer in the function app output:
@ -419,7 +423,7 @@ There are many ways to request the same thing, such as setting a timer. Think of
## Post-lecture quiz
[Post-lecture quiz](https://brave-island-0b7c7f50f.azurestaticapps.net/quiz/34)
[Post-lecture quiz](https://brave-island-0b7c7f50f.azurestaticapps.net/quiz/44)
## Review & Self Study

@ -2,7 +2,7 @@
## Instructions
So far in this lesson you have trained a model to understand setting a timer. Another useful feature is cancelling a timer - maybe your bread is ready and can be taken out of the oven.
So far in this lesson you have trained a model to understand setting a timer. Another useful feature is cancelling a timer - maybe your bread is ready and can be taken out of the oven before the timer is elapsed.
Add a new intent to your LUIS app to cancel the timer. It won't need any entities, but will need some example sentences. Handle this in your serverless code if it is the top intent, logging that the intent was recognized.

@ -28,16 +28,16 @@ def main(events: List[func.EventHubEvent]):
if prediction_response.prediction.top_intent == 'set timer':
numbers = prediction_response.prediction.entities['number']
time_units = prediction_response.prediction.entities['time unit']
total_time = 0
total_seconds = 0
for i in range(0, len(numbers)):
number = numbers[i]
time_unit = time_units[i][0]
if time_unit == 'minute':
total_time += number * 60
total_seconds += number * 60
else:
total_time += number
total_seconds += number
logging.info(f'Timer required for {total_time} seconds')
logging.info(f'Timer required for {total_seconds} seconds')

@ -6,28 +6,145 @@ Add a sketchnote if possible/appropriate
## Pre-lecture quiz
[Pre-lecture quiz](https://brave-island-0b7c7f50f.azurestaticapps.net/quiz/33)
[Pre-lecture quiz](https://brave-island-0b7c7f50f.azurestaticapps.net/quiz/45)
## Introduction
In this lesson you will learn about
Smart assistants are not one-way communication devices. You speak to them, and they respond:
"Alexa, set a 3 minute timer"
"Ok, your timer is set for 3 minutes"
In the last 2 lessons you learned how to take speech and create text, then extract a set timer request from that text. In this lesson you will learn how to set the timer on the IoT device, responding to the user with spoken words confirming their timer, and alerting them when their timer is finished.
In this lesson we'll cover:
* [Thing 1](#thing-1)
* [Text to speech](#text-to-speech)
* [Set the timer](#set-the-timer)
* [Convert text to speech](#convert-text-to-speech)
## Text to speech
Text to speech, as the name suggests, is the process of converting text into audio that contains the text as spoken words. The basic principle is to break down the words in the text into their constituent sounds (known as phonemes), and stitch together audio for those sounds, either using pre-recorded audio or using audio generated by AI models.
![The three stages of typical text to speech systems](../../../images/tts-overview.png)
Text to speech systems typically have 3 stages:
* Text analysis
* Linguistic analysis
* Wave-form generation
### Text analysis
Text analysis involves taking the text provided, and converting into words that can be used to generate speech. For example, if you convert "Hello world", there there is no text analysis needed, the two words can be converted to speech. If you have "1234" however, then this might need to be converted either into the words "One thousand, two hundred thirty four" or "One, two, three, four" depending on the context. For "I have 1234 apples", then it would be "One thousand, two hundred thirty four", but for "The child counted 1234" then it would be "One, two, three, four".
The words created vary not only for the language, but the locale of that language. For example, in American English, 120 would be "One hundred twenty", in British English it would be "One hundred and twenty", with the use of "and" after the hundreds.
✅ Some other examples that require text analysis include "in" as a short form of inch, and "st" as a short form of saint and street. Can you think of other examples in your language of words that are ambiguous without context.
Once the words have been defined, they are sent for linguistic analysis.
### Linguistic analysis
Linguistic analysis breaks the words down into phonemes. Phonemes are based not just on the letters used, but the other letters in the word. For example, in English the 'a' sound in 'car' and 'care' is different. The English language has 44 different phonemes for the 26 letters in the alphabet, some shared by different letters, such as the same phoneme used at the start of 'circle' and 'serpent'.
✅ Do some research: What are the phonemes for you language?
Once the words have been converted to phonemes, these phonemes need additional data to support intonation, adjusting the tone or duration depending on the context. One example is in English pitch increases can be used to convert a sentence into a question, having a raised pitch for the last word implies a question.
For example - the sentence "You have an apple" is a statement saying that you have an apple. If the pitch goes up at the end, increasing for the word apple, it becomes the question "You have an apple?", asking if you have an apple. The linguistic analysis needs to use the question mark at the end to decide to increase pitch.
Once the phonemes have been generated, they can be sent for wave-form generation to produce the audio output.
### Wave-form generation
The first electronic text to speech systems used single audio recordings for each phoneme, leading to very monotonous, robotic sounding voices. The linguistic analysis would produce phonemes, these would be loaded from a database of sounds and stitched together to make the audio.
✅ Do some research: Find some audio recordings from early speech synthesis systems. Compare it to modern speech synthesis, such as that used in smart assistants.
More modern wave-form generation uses ML models built using deep learning (very large neural networks that act in a similar way to neurons in the brain) to produce more natural sounding voices that can be indistinguishable from humans.
> 💁 Some of these ML models can be re-trained using transfer learning to sound like real people. This means using voice as a security system, something banks are increasingly trying to do, is no longer a good idea as anyone with a recording of a few minutes of your voice can impersonate you.
These large ML models are being trained to combine all three steps into end-to-end speech synthesizers.
## Thing 1
## Set the timer
The timer can be set by sending a command from the serverless code, instructing the IoT device to set the timer. This command will contain the time in seconds till the timer needs to go off.
### Task - set the timer using a command
1. In your serverless code, add code to send a direct method request to your IoT device
> ⚠️ You can refer to [the instructions for sending direct method requests in lesson 5 of the farm project if needed](../../../2-farm/lessons/5-migrate-application-to-the-cloud/README.md#send-direct-method-requests-from-serverless-code).
You will need to set up the connection string for the IoT Hub with the service policy (*NOT* the device) in your `local.settings.json` file and add the `azure-iot-hub` pip package to your `requirements.txt` file. The device ID can be extracted from the event.
1. The direct method you send needs to be called `set-timer`, and will need to send the length of the timer as a JSON property called `seconds`. Use the following code to build the `CloudToDeviceMethod` using the `total_seconds` calculated from the data extracted by LUIS:
```python
payload = {
'seconds': total_seconds
}
direct_method = CloudToDeviceMethod(method_name='set-timer', payload=json.dumps(payload))
```
> 💁 You can find this code in the [code-command/functions](code-command/functions) folder.
### Task - respond to the command on the IoT device
1. On your IoT device, respond to the command.
> ⚠️ You can refer to [the instructions for handling direct method requests from IoT devices in lesson 4 of the farm project if needed](../../../2-farm/lessons/4-migrate-your-plant-to-the-cloud#task---connect-your-iot-device-to-the-cloud).
1. Work through the relevant guide to set a timer for the required time:
* [Arduino - Wio Terminal](wio-terminal-set-timer.md)
* [Single-board computer - Raspberry Pi/Virtual IoT device](single-board-computer-set-timer.md)
## Convert text to speech
The same speech service you used to convert speech to text can be used to convert text back into speech, and this can be played through a speaker on your IoT device. The text to convert is sent to the speech service, along with the type of audio required (such as the sample rate), and binary data containing the audio is returned.
When you send this request, you send it using *Speech Synthesis Markup Language* (SSML), an XML-based markup language for speech synthesis applications. This defines not only the text to be converted, but the language of the text, the voice to use, and can even be used to define speed, volume, and pitch for some or all of the words in the text.
For example, this SSML defines a request to convert the text "Your 3 minute 5 second time has been set" to speech using a British English voice called `en-GB-MiaNeural`
```xml
<speak version='1.0' xml:lang='en-GB'>
<voice xml:lang='en-GB' name='en-GB-MiaNeural'>
Your 3 minute 5 second time has been set
</voice>
</speak>
```
> 💁 Most text to speech systems have multiple voices for different languages, with relevant accents such as a British English voice with an English accent and a New Zealand English voice with a New Zealand accent.
### Task - convert text to speech
Work through the relevant guide to convert text to speech using your IoT device:
* [Arduino - Wio Terminal](wio-terminal-text-to-speech.md)
* [Single-board computer - Raspberry Pi](pi-text-to-speech.md)
* [Single-board computer - Virtual device](virtual-device-text-to-speech.md)
---
## 🚀 Challenge
SSML has ways to change how words are spoken, such as adding emphasis to certain words, adding pauses, or changing pitch. Try some of these out, sending different SSML from your IoT device and comparing the output. You can read more about SSML, including how to change the way words are spoken in the [Speech Synthesis Markup Language (SSML) Version 1.1 specification from the World Wide Web consortium](https://www.w3.org/TR/speech-synthesis11/).
## Post-lecture quiz
[Post-lecture quiz](https://brave-island-0b7c7f50f.azurestaticapps.net/quiz/34)
[Post-lecture quiz](https://brave-island-0b7c7f50f.azurestaticapps.net/quiz/46)
## Review & Self Study
* Read more on speech synthesis on the [Speech synthesis page on Wikipedia](https://wikipedia.org/wiki/Speech_synthesis)
* Read more on ways criminals are using speech synthesis to steal on the [Fake voices 'help cyber crooks steal cash' story on BBC news](https://www.bbc.com/news/technology-48908736)
## Assignment
[](assignment.md)
[Cancel the timer](assignment.md)

@ -1,9 +1,12 @@
#
# Cancel the timer
## Instructions
In the assignment for the last lesson, you added a cancel timer intent to LUIS. For this assignment you need to handle this intent in the serverless code, send a command to the IoT device, then cancel the timer.
## Rubric
| Criteria | Exemplary | Adequate | Needs Improvement |
| -------- | --------- | -------- | ----------------- |
| | | | |
| Handle the intent in serverless code and send a command | Was able to handle the intent and send a command to the device | Was able to handle the intent but was unable to send the command to the device | Was unable to handle the intent |
| Cancel the timer on the device | Was able to receive the command and cancel the timer | Was able to receive the command but not cancel the timer | Was unable to receive the command |

@ -0,0 +1,15 @@
{
"version": "2.0",
"logging": {
"applicationInsights": {
"samplingSettings": {
"isEnabled": true,
"excludedTypes": "Request"
}
}
},
"extensionBundle": {
"id": "Microsoft.Azure.Functions.ExtensionBundle",
"version": "[2.*, 3.0.0)"
}
}

@ -0,0 +1,12 @@
{
"IsEncrypted": false,
"Values": {
"FUNCTIONS_WORKER_RUNTIME": "python",
"AzureWebJobsStorage": "UseDevelopmentStorage=true",
"IOT_HUB_CONNECTION_STRING": "<connection string>",
"LUIS_KEY": "<primary key>",
"LUIS_ENDPOINT_URL": "<endpoint url>",
"LUIS_APP_ID": "<app id>",
"REGISTRY_MANAGER_CONNECTION_STRING": "<connection string>"
}
}

@ -0,0 +1,4 @@
# Do not include azure-functions-worker as it may conflict with the Azure Functions platform
azure-functions
azure-cognitiveservices-language-luis

@ -0,0 +1,60 @@
from typing import List
import logging
import azure.functions as func
import json
import os
from azure.cognitiveservices.language.luis.runtime import LUISRuntimeClient
from msrest.authentication import CognitiveServicesCredentials
from azure.iot.hub import IoTHubRegistryManager
from azure.iot.hub.models import CloudToDeviceMethod
def main(events: List[func.EventHubEvent]):
luis_key = os.environ['LUIS_KEY']
endpoint_url = os.environ['LUIS_ENDPOINT_URL']
app_id = os.environ['LUIS_APP_ID']
registry_manager_connection_string = os.environ['REGISTRY_MANAGER_CONNECTION_STRING']
credentials = CognitiveServicesCredentials(luis_key)
client = LUISRuntimeClient(endpoint=endpoint_url, credentials=credentials)
for event in events:
logging.info('Python EventHub trigger processed an event: %s',
event.get_body().decode('utf-8'))
device_id = event.iothub_metadata['connection-device-id']
event_body = json.loads(event.get_body().decode('utf-8'))
prediction_request = { 'query' : event_body['speech'] }
prediction_response = client.prediction.get_slot_prediction(app_id, 'Staging', prediction_request)
if prediction_response.prediction.top_intent == 'set timer':
numbers = prediction_response.prediction.entities['number']
time_units = prediction_response.prediction.entities['time unit']
total_seconds = 0
for i in range(0, len(numbers)):
number = numbers[i]
time_unit = time_units[i][0]
if time_unit == 'minute':
total_seconds += number * 60
else:
total_seconds += number
logging.info(f'Timer required for {total_seconds} seconds')
payload = {
'seconds': total_seconds
}
direct_method = CloudToDeviceMethod(method_name='set-timer', payload=json.dumps(payload))
registry_manager_connection_string = os.environ['REGISTRY_MANAGER_CONNECTION_STRING']
registry_manager = IoTHubRegistryManager(registry_manager_connection_string)
registry_manager.invoke_device_method(device_id, direct_method)

@ -0,0 +1,15 @@
{
"scriptFile": "__init__.py",
"bindings": [
{
"type": "eventHubTrigger",
"name": "events",
"direction": "in",
"eventHubName": "samples-workitems",
"connection": "IOT_HUB_CONNECTION_STRING",
"cardinality": "many",
"consumerGroup": "$Default",
"dataType": "binary"
}
]
}

@ -0,0 +1,184 @@
import io
import json
import pyaudio
import requests
import time
import wave
import threading
from azure.iot.device import IoTHubDeviceClient, Message, MethodResponse
from grove.factory import Factory
button = Factory.getButton('GPIO-HIGH', 5)
audio = pyaudio.PyAudio()
microphone_card_number = 1
speaker_card_number = 1
rate = 16000
def capture_audio():
stream = audio.open(format = pyaudio.paInt16,
rate = rate,
channels = 1,
input_device_index = microphone_card_number,
input = True,
frames_per_buffer = 4096)
frames = []
while button.is_pressed():
frames.append(stream.read(4096))
stream.stop_stream()
stream.close()
wav_buffer = io.BytesIO()
with wave.open(wav_buffer, 'wb') as wavefile:
wavefile.setnchannels(1)
wavefile.setsampwidth(audio.get_sample_size(pyaudio.paInt16))
wavefile.setframerate(rate)
wavefile.writeframes(b''.join(frames))
wav_buffer.seek(0)
return wav_buffer
speech_api_key = '<key>'
location = '<location>'
language = '<language>'
connection_string = '<connection_string>'
device_client = IoTHubDeviceClient.create_from_connection_string(connection_string)
print('Connecting')
device_client.connect()
print('Connected')
def get_access_token():
headers = {
'Ocp-Apim-Subscription-Key': speech_api_key
}
token_endpoint = f'https://{location}.api.cognitive.microsoft.com/sts/v1.0/issuetoken'
response = requests.post(token_endpoint, headers=headers)
return str(response.text)
def convert_speech_to_text(buffer):
url = f'https://{location}.stt.speech.microsoft.com/speech/recognition/conversation/cognitiveservices/v1'
headers = {
'Authorization': 'Bearer ' + get_access_token(),
'Content-Type': f'audio/wav; codecs=audio/pcm; samplerate={rate}',
'Accept': 'application/json;text/xml'
}
params = {
'language': language
}
response = requests.post(url, headers=headers, params=params, data=buffer)
response_json = json.loads(response.text)
if response_json['RecognitionStatus'] == 'Success':
return response_json['DisplayText']
else:
return ''
def get_voice():
url = f'https://{location}.tts.speech.microsoft.com/cognitiveservices/voices/list'
headers = {
'Authorization': 'Bearer ' + get_access_token()
}
response = requests.get(url, headers=headers)
voices_json = json.loads(response.text)
first_voice = next(x for x in voices_json if x['Locale'].lower() == language.lower())
return first_voice['ShortName']
voice = get_voice()
print(f'Using voice {voice}')
playback_format = 'riff-48khz-16bit-mono-pcm'
def get_speech(text):
url = f'https://{location}.tts.speech.microsoft.com/cognitiveservices/v1'
headers = {
'Authorization': 'Bearer ' + get_access_token(),
'Content-Type': 'application/ssml+xml',
'X-Microsoft-OutputFormat': playback_format
}
ssml = f'<speak version=\'1.0\' xml:lang=\'{language}\'>'
ssml += f'<voice xml:lang=\'{language}\' name=\'{voice}\'>'
ssml += text
ssml += '</voice>'
ssml += '</speak>'
response = requests.post(url, headers=headers, data=ssml.encode('utf-8'))
return io.BytesIO(response.content)
def play_speech(speech):
with wave.open(speech, 'rb') as wave_file:
stream = audio.open(format=audio.get_format_from_width(wave_file.getsampwidth()),
channels=wave_file.getnchannels(),
rate=wave_file.getframerate(),
output_device_index=speaker_card_number,
output=True)
data = wave_file.readframes(4096)
while len(data) > 0:
stream.write(data)
data = wave_file.readframes(4096)
stream.stop_stream()
stream.close()
def say(text):
speech = get_speech(text)
play_speech(speech)
def announce_timer(minutes, seconds):
announcement = 'Times up on your '
if minutes > 0:
announcement += f'{minutes} minute '
if seconds > 0:
announcement += f'{seconds} second '
announcement += 'timer.'
say(announcement)
def create_timer(total_seconds):
minutes, seconds = divmod(total_seconds, 60)
threading.Timer(total_seconds, announce_timer, args=[minutes, seconds]).start()
announcement = ''
if minutes > 0:
announcement += f'{minutes} minute '
if seconds > 0:
announcement += f'{seconds} second '
announcement += 'timer started.'
say(announcement)
def handle_method_request(request):
if request.name == 'set-timer':
payload = json.loads(request.payload)
seconds = payload['seconds']
if seconds > 0:
create_timer(payload['seconds'])
method_response = MethodResponse.create_from_method_request(request, 200)
device_client.send_method_response(method_response)
device_client.on_method_request_received = handle_method_request
while True:
while not button.is_pressed():
time.sleep(.1)
buffer = capture_audio()
text = convert_speech_to_text(buffer)
if len(text) > 0:
print(text)
message = Message(json.dumps({ 'speech': text }))
device_client.send_message(message)

@ -0,0 +1,86 @@
import json
import threading
import time
from azure.cognitiveservices.speech import SpeechConfig, SpeechRecognizer, SpeechSynthesizer
from azure.iot.device import IoTHubDeviceClient, Message, MethodResponse
speech_api_key = '<key>'
location = '<location>'
language = '<language>'
connection_string = '<connection_string>'
device_client = IoTHubDeviceClient.create_from_connection_string(connection_string)
print('Connecting')
device_client.connect()
print('Connected')
recognizer_config = SpeechConfig(subscription=speech_api_key,
region=location,
speech_recognition_language=language)
recognizer = SpeechRecognizer(speech_config=recognizer_config)
def recognized(args):
if len(args.result.text) > 0:
message = Message(json.dumps({ 'speech': args.result.text }))
device_client.send_message(message)
recognizer.recognized.connect(recognized)
recognizer.start_continuous_recognition()
speech_config = SpeechConfig(subscription=speech_api_key,
region=location)
speech_config.speech_synthesis_language = language
speech_synthesizer = SpeechSynthesizer(speech_config=speech_config)
voices = speech_synthesizer.get_voices_async().get().voices
first_voice = next(x for x in voices if x.locale.lower() == language.lower())
speech_config.speech_synthesis_voice_name = first_voice.short_name
def say(text):
ssml = f'<speak version=\'1.0\' xml:lang=\'{language}\'>'
ssml += f'<voice xml:lang=\'{language}\' name=\'{first_voice.short_name}\'>'
ssml += text
ssml += '</voice>'
ssml += '</speak>'
recognizer.stop_continuous_recognition()
speech_synthesizer.speak_ssml(ssml)
recognizer.start_continuous_recognition()
def announce_timer(minutes, seconds):
announcement = 'Times up on your '
if minutes > 0:
announcement += f'{minutes} minute '
if seconds > 0:
announcement += f'{seconds} second '
announcement += 'timer.'
say(announcement)
def create_timer(total_seconds):
minutes, seconds = divmod(total_seconds, 60)
threading.Timer(total_seconds, announce_timer, args=[minutes, seconds]).start()
announcement = ''
if minutes > 0:
announcement += f'{minutes} minute '
if seconds > 0:
announcement += f'{seconds} second '
announcement += 'timer started.'
say(announcement)
def handle_method_request(request):
if request.name == 'set-timer':
payload = json.loads(request.payload)
seconds = payload['seconds']
if seconds > 0:
create_timer(payload['seconds'])
method_response = MethodResponse.create_from_method_request(request, 200)
device_client.send_method_response(method_response)
device_client.on_method_request_received = handle_method_request
while True:
time.sleep(1)

@ -0,0 +1,130 @@
import io
import json
import pyaudio
import requests
import time
import wave
import threading
from azure.iot.device import IoTHubDeviceClient, Message, MethodResponse
from grove.factory import Factory
button = Factory.getButton('GPIO-HIGH', 5)
audio = pyaudio.PyAudio()
microphone_card_number = 1
speaker_card_number = 1
rate = 16000
def capture_audio():
stream = audio.open(format = pyaudio.paInt16,
rate = rate,
channels = 1,
input_device_index = microphone_card_number,
input = True,
frames_per_buffer = 4096)
frames = []
while button.is_pressed():
frames.append(stream.read(4096))
stream.stop_stream()
stream.close()
wav_buffer = io.BytesIO()
with wave.open(wav_buffer, 'wb') as wavefile:
wavefile.setnchannels(1)
wavefile.setsampwidth(audio.get_sample_size(pyaudio.paInt16))
wavefile.setframerate(rate)
wavefile.writeframes(b''.join(frames))
wav_buffer.seek(0)
return wav_buffer
speech_api_key = '<key>'
location = '<location>'
language = '<language>'
connection_string = '<connection_string>'
device_client = IoTHubDeviceClient.create_from_connection_string(connection_string)
print('Connecting')
device_client.connect()
print('Connected')
def get_access_token():
headers = {
'Ocp-Apim-Subscription-Key': speech_api_key
}
token_endpoint = f'https://{location}.api.cognitive.microsoft.com/sts/v1.0/issuetoken'
response = requests.post(token_endpoint, headers=headers)
return str(response.text)
def convert_speech_to_text(buffer):
url = f'https://{location}.stt.speech.microsoft.com/speech/recognition/conversation/cognitiveservices/v1'
headers = {
'Authorization': 'Bearer ' + get_access_token(),
'Content-Type': f'audio/wav; codecs=audio/pcm; samplerate={rate}',
'Accept': 'application/json;text/xml'
}
params = {
'language': language
}
response = requests.post(url, headers=headers, params=params, data=buffer)
response_json = json.loads(response.text)
if response_json['RecognitionStatus'] == 'Success':
return response_json['DisplayText']
else:
return ''
def say(text):
print(text)
def announce_timer(minutes, seconds):
announcement = 'Times up on your '
if minutes > 0:
announcement += f'{minutes} minute '
if seconds > 0:
announcement += f'{seconds} second '
announcement += 'timer.'
say(announcement)
def create_timer(total_seconds):
minutes, seconds = divmod(total_seconds, 60)
threading.Timer(total_seconds, announce_timer, args=[minutes, seconds]).start()
announcement = ''
if minutes > 0:
announcement += f'{minutes} minute '
if seconds > 0:
announcement += f'{seconds} second '
announcement += 'timer started.'
say(announcement)
def handle_method_request(request):
if request.name == 'set-timer':
payload = json.loads(request.payload)
seconds = payload['seconds']
if seconds > 0:
create_timer(payload['seconds'])
method_response = MethodResponse.create_from_method_request(request, 200)
device_client.send_method_response(method_response)
device_client.on_method_request_received = handle_method_request
while True:
while not button.is_pressed():
time.sleep(.1)
buffer = capture_audio()
text = convert_speech_to_text(buffer)
if len(text) > 0:
print(text)
message = Message(json.dumps({ 'speech': text }))
device_client.send_message(message)

@ -0,0 +1,69 @@
import json
import threading
import time
from azure.cognitiveservices.speech import SpeechConfig, SpeechRecognizer
from azure.iot.device import IoTHubDeviceClient, Message, MethodResponse
speech_api_key = '<key>'
location = '<location>'
language = '<language>'
connection_string = '<connection_string>'
device_client = IoTHubDeviceClient.create_from_connection_string(connection_string)
print('Connecting')
device_client.connect()
print('Connected')
recognizer_config = SpeechConfig(subscription=speech_api_key,
region=location,
speech_recognition_language=language)
recognizer = SpeechRecognizer(speech_config=recognizer_config)
def recognized(args):
if len(args.result.text) > 0:
message = Message(json.dumps({ 'speech': args.result.text }))
device_client.send_message(message)
recognizer.recognized.connect(recognized)
recognizer.start_continuous_recognition()
def say(text):
print(text)
def announce_timer(minutes, seconds):
announcement = 'Times up on your '
if minutes > 0:
announcement += f'{minutes} minute '
if seconds > 0:
announcement += f'{seconds} second '
announcement += 'timer.'
say(announcement)
def create_timer(total_seconds):
minutes, seconds = divmod(total_seconds, 60)
threading.Timer(total_seconds, announce_timer, args=[minutes, seconds]).start()
announcement = ''
if minutes > 0:
announcement += f'{minutes} minute '
if seconds > 0:
announcement += f'{seconds} second '
announcement += 'timer started.'
say(announcement)
def handle_method_request(request):
if request.name == 'set-timer':
payload = json.loads(request.payload)
seconds = payload['seconds']
if seconds > 0:
create_timer(payload['seconds'])
method_response = MethodResponse.create_from_method_request(request, 200)
device_client.send_method_response(method_response)
device_client.on_method_request_received = handle_method_request
while True:
time.sleep(1)

@ -0,0 +1,142 @@
# Text to speech - Raspberry Pi
In this part of the lesson, you will write code to convert text to speech using the speech service.
## Convert text to speech using the speech service
The text can be sent to the speech service using the REST API to get speech as an audio file that can be played back on your IoT device. When requesting speech, you need to provide the voice to use as speech can be generated using a variety of different voices.
Each language supports a range of different voices, and you can make a REST request against the speech service to get the list of supported voices for each language.
### Task - get a voice
1. Open the `smart-timer` project in VS Code.
1. Add the following code above the `say` function to request the list of voices for a language:
```python
def get_voice():
url = f'https://{location}.tts.speech.microsoft.com/cognitiveservices/voices/list'
headers = {
'Authorization': 'Bearer ' + get_access_token()
}
response = requests.get(url, headers=headers)
voices_json = json.loads(response.text)
first_voice = next(x for x in voices_json if x['Locale'].lower() == language.lower() and x['VoiceType'] == 'Neural')
return first_voice['ShortName']
voice = get_voice()
print(f'Using voice {voice}')
```
This code defines a function called `get_voice` that uses the speech service to get a list of voices. It then finds the first voice that matches the language that is being used.
This function is then called to store the first voice, and the voice name is printed to the console. This voice can be requested once and the value used for every call to convert text to speech.
> 💁 You can get the full list of supported voices from the [Language and voice support documentation on Microsoft Docs](https://docs.microsoft.com/azure/cognitive-services/speech-service/language-support?WT.mc_id=academic-17441-jabenn#text-to-speech). If you want to use a specific voice, then you can remove this function and hard code the voice to the voice name from this documentation. For example:
>
> ```python
> voice = 'hi-IN-SwaraNeural'
> ```
### Task - convert text to speech
1. Below this, define a constant for the audio format to be retrieved from the speech services. When you request audio, you can do it in a range of different formats.
```python
playback_format = 'riff-48khz-16bit-mono-pcm'
```
The format you can use depends on your hardware. If you get `Invalid sample rate` errors when playing the audio then change this to another value. You can find the list of supported values in the [Text to speech REST API documentation on Microsoft Docs](https://docs.microsoft.com/azure/cognitive-services/speech-service/rest-text-to-speech?WT.mc_id=academic-17441-jabenn#audio-outputs). You will need to use `riff` format audio, and the values to try are `riff-16khz-16bit-mono-pcm`, `riff-24khz-16bit-mono-pcm` and `riff-48khz-16bit-mono-pcm`.
1. Below this, declare a function called `get_speech` that will convert the text to speech using the speech service REST API:
```python
def get_speech(text):
```
1. In the `get_speech` function, define the URL to call and the headers to pass:
```python
url = f'https://{location}.tts.speech.microsoft.com/cognitiveservices/v1'
headers = {
'Authorization': 'Bearer ' + get_access_token(),
'Content-Type': 'application/ssml+xml',
'X-Microsoft-OutputFormat': playback_format
}
```
This set the headers to use a generated access token, set the content to SSML and define the audio format needed.
1. Below this, define the SSML to send to the REST API:
```python
ssml = f'<speak version=\'1.0\' xml:lang=\'{language}\'>'
ssml += f'<voice xml:lang=\'{language}\' name=\'{voice}\'>'
ssml += text
ssml += '</voice>'
ssml += '</speak>'
```
This SSML sets the language and the voice to use, along with the text to convert.
1. Finally, add code in this function to make the REST request and return the binary audio data:
```python
response = requests.post(url, headers=headers, data=ssml.encode('utf-8'))
return io.BytesIO(response.content)
```
### Task - play the audio
1. Below the `get_speech` function, define a new function to play the audio returned by the REST API call:
```python
def play_speech(speech):
```
1. The `speech` passed to this function will be the binary audio data returned from the REST API. Use the following code to open this as a wave file and pass it to PyAudio to play the audio:
```python
def play_speech(speech):
with wave.open(speech, 'rb') as wave_file:
stream = audio.open(format=audio.get_format_from_width(wave_file.getsampwidth()),
channels=wave_file.getnchannels(),
rate=wave_file.getframerate(),
output_device_index=speaker_card_number,
output=True)
data = wave_file.readframes(4096)
while len(data) > 0:
stream.write(data)
data = wave_file.readframes(4096)
stream.stop_stream()
stream.close()
```
This code uses a PyAudio stream, the same as capturing audio. The difference here is the stream is set as an output stream, and data is read from the audio data and pushed to the stream.
Rather than hard coding the stream details such as the sample rate, it is read from the audio data.
1. Replace the contents of the `say` function to the following:
```python
speech = get_speech(text)
play_speech(speech)
```
This code converts the text to speech as binary audio data, and plays the audio.
1. Run the app, and ensure the function app is also running. Set some timers, and you will hear a spoken response saying that your timer has been set, then another spoken response when the timer is complete.
If you get `Invalid sample rate` errors, change the `playback_format` as described above.
> 💁 You can find this code in the [code-spoken-response/pi](code-spoken-response/pi) folder.
😀 Your timer program was a success!

@ -0,0 +1,97 @@
# Set a timer - Virtual IoT Hardware and Raspberry Pi
In this part of the lesson, you will set a timer on your virtual IoT device or Raspberry Pi based off a command from the IoT Hub.
## Set a timer
The command sent from the serverless function contains the time for the timer in seconds as the payload. This time can be used to set a timer.
Timers can be set using the Python `threading.Timer` class. This class takes a delay time and a function, and after the delay time, the function is executed.
### Task - set a timer
1. Open the `smart-timer` project in VS Code, and ensure the virtual environment is loaded in the terminal if you are using a virtual IoT device.
1. Add the following import statement at the top of the file to import the threading Python library:
```python
import threading
```
1. Above the `handle_method_request` function that handles the method request, add a function to speak a response. Fow now this will just write to the console, but later in this lesson this will speak the text.
```python
def say(text):
print(text)
```
1. Below this add a function that will be called by a timer to announce that the timer is complete:
```python
def announce_timer(minutes, seconds):
announcement = 'Times up on your '
if minutes > 0:
announcement += f'{minutes} minute '
if seconds > 0:
announcement += f'{seconds} second '
announcement += 'timer.'
say(announcement)
```
This function takes the number of minutes and seconds for the timer, and builds a sentence to say that the timer is complete. It will check the number of minutes and seconds, and only include each time unit if it has a number. For example, if the number of minutes is 0 then only seconds are included in the message. This sentence is then sent to the `say` function.
1. Below this, add the following `create_timer` function to create a timer:
```python
def create_timer(seconds):
minutes, seconds = divmod(seconds, 60)
threading.Timer(seconds, announce_timer, args=[minutes, seconds]).start()
```
This function takes the total number of seconds for the timer that will be sent in the command, and converts this to minutes and seconds. It then creates and starts a timer object using the total number of seconds, passing in the `announce_timer` function and a list containing the minutes and seconds. When the timer elapses, it will call the `announce_timer` function, and pass the contents of this list as the parameters - so the first item in the list gets passes as the `minutes` parameter, and the second item as the `seconds` parameter.
1. To the end of the `create_timer` function, add some code to build a message to be spoken to the user to announce that the timer is starting:
```python
announcement = ''
if minutes > 0:
announcement += f'{minutes} minute '
if seconds > 0:
announcement += f'{seconds} second '
announcement += 'timer started.'
say(announcement)
```
Again, this only includes the time unit that has a value. This sentence is then sent to the `say` function.
1. At the start of the `handle_method_request` function, add the following code to check that the `set-timer` direct method was requested:
```python
if request.name == 'set-timer':
```
1. Inside this `if` statement, extract the timer time in seconds from the payload and use this to create a timer:
```python
payload = json.loads(request.payload)
seconds = payload['seconds']
if seconds > 0:
create_timer(payload['seconds'])
```
The timer is only created if the number of seconds is greater than 0
1. Run the app, and ensure the function app is also running. Set some timers, and the output will show the timer being set, and then will show when it elapses:
```output
pi@raspberrypi:~/smart-timer $ python3 app.py
Connecting
Connected
Set a one minute 4 second timer.
1 minute 4 second timer started.
Times up on your 1 minute 4 second timer.
```
> 💁 You can find this code in the [code-timer/pi](code-timer/pi) or [code-timer/virtual-iot-device](code-timer/virtual-iot-device) folder.
😀 Your timer program was a success!

@ -0,0 +1,74 @@
# Text to speech - Virtual IoT device
In this part of the lesson, you will write code to convert text to speech using the speech service.
## Convert text to speech
The speech services SDK that you used in the last lesson to convert speech to text can be used to convert text back to speech. When requesting speech, you need to provide the voice to use as speech can be generated using a variety of different voices.
Each language supports a range of different voices, and you can get the list of supported voices for each language from the speech services SDK.
### Task - convert text to speech
1. Open the `smart-timer` project in VS Code, and ensure the virtual environment is loaded in the terminal.
1. Import the `SpeechSynthesizer` from the `azure.cognitiveservices.speech` package by adding it to the existing imports:
```python
from azure.cognitiveservices.speech import SpeechConfig, SpeechRecognizer, SpeechSynthesizer
```
1. Above the `say` function, create a speech configuration to use with the speech synthesizer:
```python
speech_config = SpeechConfig(subscription=speech_api_key,
region=location)
speech_config.speech_synthesis_language = language
speech_synthesizer = SpeechSynthesizer(speech_config=speech_config)
```
This uses the same API key, location and language that was used by the recognizer.
1. Below this, add the following code to get a voice and set it on the speech config:
```python
voices = speech_synthesizer.get_voices_async().get().voices
first_voice = next(x for x in voices if x.locale.lower() == language.lower())
speech_config.speech_synthesis_voice_name = first_voice.short_name
```
This retrieves a list of all the available voices, then finds the first voice that matches the language that is being used.
> 💁 You can get the full list of supported voices from the [Language and voice support documentation on Microsoft Docs](https://docs.microsoft.com/azure/cognitive-services/speech-service/language-support?WT.mc_id=academic-17441-jabenn#text-to-speech). If you want to use a specific voice, then you can remove this function and hard code the voice to the voice name from this documentation. For example:
>
> ```python
> speech_config.speech_synthesis_voice_name = 'hi-IN-SwaraNeural'
> ```
1. Update the contents of the `say` function to generate SSML for the response:
```python
ssml = f'<speak version=\'1.0\' xml:lang=\'{language}\'>'
ssml += f'<voice xml:lang=\'{language}\' name=\'{first_voice.short_name}\'>'
ssml += text
ssml += '</voice>'
ssml += '</speak>'
```
1. Below this, stop the speech recognition, speak the SSML, then start the recognition again:
```python
recognizer.stop_continuous_recognition()
speech_synthesizer.speak_ssml(ssml)
recognizer.start_continuous_recognition()
```
The recognition is stopped whilst the text is spoken to avoid the announcement of the timer starting being detected, sent to LUIS and possibly interpreted as a request to set a new timer.
> 💁 You can test this out by commenting out the lines to stop and restart the recognition. Set one timer, and you may find the announcement sets a new timer, which causes a new announcement, leading to a new timer, and so on for ever!
1. Run the app, and ensure the function app is also running. Set some timers, and you will hear a spoken response saying that your timer has been set, then another spoken response when the timer is complete.
> 💁 You can find this code in the [code-spoken-response/virtual-iot-device](code-spoken-response/virtual-iot-device) folder.
😀 Your timer program was a success!

@ -0,0 +1,3 @@
# Set a timer - Wio Terminal
Coming soon

@ -0,0 +1,3 @@
# Text to speech - Wio Terminal
Coming soon

@ -2,32 +2,169 @@
Add a sketchnote if possible/appropriate
![Embed a video here if available](video-url)
This video gives an overview of the Azure speech services, covering speech to text and text to speech from earlier lessons, as well as translating speech, a topic covered in this lesson:
[![Recognizing speech with a few lines of Python from Microsoft Build 2020](https://img.youtube.com/vi/h6xbpMPSGEA/0.jpg)](https://www.youtube.com/watch?v=h6xbpMPSGEA)
> 🎥 Click the image above to watch the video
## Pre-lecture quiz
[Pre-lecture quiz](https://brave-island-0b7c7f50f.azurestaticapps.net/quiz/33)
[Pre-lecture quiz](https://brave-island-0b7c7f50f.azurestaticapps.net/quiz/47)
## Introduction
In this lesson you will learn about
In the last 3 lessons you learned about converting speech to text, language understanding, and converting text to speech, all powered by AI. One other area of human communication that AI can help with is language translation - converting from one language to another, such as from English to French.
In this lesson you will learn about using AI to translate text, allowing your smart timer to interact with users in multiple languages.
In this lesson we'll cover:
* [Thing 1](#thing-1)
* [Translate text](#translate-text)
* [Translation services](#translation-services)
* [Create a translator resource](#create-a-translator-resource)
* [Support multiple languages in applications with translations](#support-multiple-languages-in-applications-with-translations)
* [Translate text using an AI service](#translate-text-using-an-ai-service)
## Translate text
Text translation has been a computer science problem that has been researched for over 70 years, and only now thanks to advances in AI and computer power is close to being solved to a point where it is almost as good as human translators.
> 💁 The origins can be traced back even further, to [Al-Kindi](https://wikipedia.org/wiki/Al-Kindi), a 9th century Arabic cryptographer who developed techniques for language translation
### Machine translations
Text translation started out as a technology known as Machine Translation (MT), that can translate between different language pairs. MT works by substituting words in one language with another, adding techniques to select the correct ways of translating phrases or parts of sentences when a simple word-for-word translation doesn't make sense.
> 🎓 When translators support translating between one language and another, these are know as *language pairs*. Different tools support different language pairs, and these may not be complete. For example, a translator may support English to Spanish as a language pair, and Spanish to Italian as a language pair, but not English to Italian.
For example, translating "Hello world" from English into French can be performed with a substitution - "Bonjour" for "Hello", and "le monde" for "world", leading to the correct translation of "Bonjour le monde".
Substitutions don't work when different languages use different ways of saying the same thing. For example, the English sentence "My name is Jim", translates into "Je m'appelle Jim" in French - literally "I call myself Jim". "Je" is French for "I", "moi" is me, but is concatenated with the verb as it starts with a vowel, so becomes "m'", "appelle" is to call, and "Jim" isn't translated as it's a name, and not a word that can be translated. Word ordering also becomes an issue - a simple substitution of "Je m'appelle Jim" becomes "I myself call Jim", with a different word order to English.
> 💁 Some words are never translated - my name is Jim regardless of which language is used to introduce me.
Idioms are also a problem for translation. These are phrases that have an understood meaning that is different from a direct interpretation of the words. For example, in English the idiom "I've got ants in my pants" does not literally refer to having ants in your clothing, but to being restless. If you translated this to German, you would end up confusing the listener, as the German version is "I have bumble bees in the bottom".
> 💁 Different locales add different complexities. With the idiom "ants in your pants", in American English "pants" refers to outerwear, in British English, "pants" is underwear.
✅ If you speak multiple languages, think of some phrases that don't directly translate
Machine translation systems rely on large databases of rules that describe how to translate certain phrases and idioms, along with statistical methods to pick the appropriate translations from possible options. These statistical methods use huge databases of works translated by humans into multiple languages to pick the most likely translation, a technique called *statistical machine translation*. A number of these use intermediate representations of the language, allowing one language to be translated to the intermediate, then from the intermediate to another language. This way adding more languages involves translations to and from the intermediate, not to and from all other languages.
### Neural translations
Neural translations involve using the power of AI to translate, typically translating entire sentences using one model. These models are trained on huge data sets that have been human translated, such as web pages, books and United Nations documentation.
Neural translation models are usually smaller than machine translation models due to not needing huge databases of phrases and idioms. Modern AI services that provide translations often mix multiple techniques, mixing statistical machine translation and neural translation
There is no 1:1 translation for any language pair. Different translation models will produce slightly different results depending on the data used to train the model. Translations are not always symmetrical - in that if you translate a sentence from one language to another, then back to the first language you may see a slightly different sentence as the result.
✅ Try out different online translators such as [Bing Translate](https://www.bing.com/translator), [Google Translate](https://translate.google.com), or the Apple translate app. Compare the translated versions of a few sentences. Also try translating in one, then translating back in another.
## Translation services
There are a number of AI services that can be used from your applications to translate speech and text.
### Cognitive services Speech service
![The speech service logo](../../../images/azure-speech-logo.png)
The speech service you've been using over the past few lessons has translation capabilities for speech recognition. When you recognize speech, you can request not only the text of the speech in the same language, but also in other languages.
> 💁 This is only available from the speech SDK, the REST API doesn't have translations built in.
### Cognitive services Translator service
![The translator service logo](../../../images/azure-translator-logo.png)
The Translator service is a dedicated translation service that can translate text from one language, to one or more target languages. As well as translating, it supports a wide range of extra features including masking profanity. It also allows you to provide a specific translation for a particular word or sentence, to work with terms you don't want translated, or have a specific well-known translation.
## Thing 1
For example, when translating the sentence "I have a Raspberry Pi", referring to the single-board computer, into another language such as French, you would want to keep the name "Raspberry Pi" as is, and not translate it, giving "Jai un Raspberry Pi" instead of "Jai une pi aux framboises".
## Create a translator resource
For this lesson you will need a Translator resource. You will use the REST API to translate text.
### Task - create a translator resource
1. From your terminal or command prompt, run the following command to create a translator resource in your `smart-timer` resource group.
```sh
az cognitiveservices account create --name smart-timer-translator \
--resource-group smart-timer \
--kind TextTranslation \
--sku F0 \
--yes \
--location <location>
```
Replace `<location>` with the location you used when creating the Resource Group.
1. Get the key for the translator service:
```sh
az cognitiveservices account keys list --name smart-timer-translator \
--resource-group smart-timer \
--output table
```
Take a copy of one of the keys.
## Support multiple languages in applications with translations
In an ideal world, your whole application should understand as many different languages as possible, from listening for speech, to language understanding, to responding with speech. This is a lot of work, so translation services can speed up the time to delivery of your application.
![A smart timer architecture translating Japanese to English, processing in English then translating back to Japanese](../../../images/translated-smart-timer.png)
***A smart timer architecture translating Japanese to English, processing in English then translating back to Japanese. Microcontroller by Template / recording by Aybige Speaker / Speaker by Gregor Cresnar - all from the [Noun Project](https://thenounproject.com)***
Imagine you are building a smart timer that uses English end-to-end, understanding spoken English and converting that to text, running the language understanding in English, building up responses in English and replying with English speech. If you wanted to add support for Japanese, you could start with translating spoken Japanese to English text, then keep the core of the application the same, then translate the response text to Japanese before speaking the response. This would allow you to quickly add Japanese support, and you can expand to providing full end-to-end Japanese support later.
> 💁 The downside to relying on machine translation is that different languages and cultures have different ways of saying the same things, so the translation may not match the expression you are expecting.
Machine translations also open up possibilities for apps and devices that can translate user-created content as it is created. Science fiction regularly features 'universal translators', devices that can translate from alien languages into (typically) American English. These devices are less science fiction, more science fact, if you ignore the alien part. There are already apps and devices that provide real-time translation of speech and written text, using combinations of speech and translation services.
One example is the [Microsoft Translator](https://www.microsoft.com/translator/apps/?WT.mc_id=academic-17441-jabenn) mobile phone app, demonstrated in this video:
[![Microsoft Translator live feature in action](https://img.youtube.com/vi/16yAGeP2FuM/0.jpg)](https://www.youtube.com/watch?v=16yAGeP2FuM)
> 🎥 Click the image above to watch the video
Imagine having such a device available to you, especially when travelling or interacting with folks whose language you don't know. Having automatic translation devices in airports or hospitals would provide much needed accessibility improvements.
✅ Do some research: Are there any translation IoT devices commercially available? What about translation capabilities built into smart devices?
> 👽 Although there are no true universal translators that allow us to talk to aliens, the [Microsoft translator does support Klingon](https://www.microsoft.com/translator/blog/2013/05/14/announcing-klingon-for-bing-translator/?WT.mc_id=academic-17441-jabenn). Qapla!
## Translate text using an AI service
You can use an AI service to add this translation capability to your smart timer.
### Task - translate text using an AI service
Work through the relevant guide to convert translate text on your IoT device:
* [Arduino - Wio Terminal](wio-terminal-translate-speech.md)
* [Single-board computer - Raspberry Pi](pi-translate-speech.md)
* [Single-board computer - Virtual device](virtual-device-translate-speech.md)
---
## 🚀 Challenge
How can machine translations benefit other IoT applications beyond smart devices? Think of different ways translations can help, not just with spoken words but with text.
## Post-lecture quiz
[Post-lecture quiz](https://brave-island-0b7c7f50f.azurestaticapps.net/quiz/34)
[Post-lecture quiz](https://brave-island-0b7c7f50f.azurestaticapps.net/quiz/48)
## Review & Self Study
* Read more on machine translation on the [Machine translation page on Wikipedia](https://wikipedia.org/wiki/Machine_translation)
* Read more on neural machine translation on the [Neural machine translation page on Wikipedia](https://wikipedia.org/wiki/Neural_machine_translation)
* Check out the list of supported languages for the Microsoft speech services in the [Language and voice support for the Speech service documentation on Microsoft Docs](https://docs.microsoft.com/azure/cognitive-services/speech-service/language-support?WT.mc_id=academic-17441-jabenn)
## Assignment
[](assignment.md)
[Build a universal translator](assignment.md)

@ -1,9 +1,17 @@
#
# Build a universal translator
## Instructions
A universal translator is a device that can translate between multiple languages, allowing folks who speak different languages to be able to communicate. Use what you have learned over the past few lessons to build a universal translator using 2 IoT devices.
> If you do not have 2 devices, follow the steps in the previous few lessons to set up a virtual IoT device as one of the IoT devices.
You should configure one device for one language, and one for another. Each device should accept speech, convert it to text, send it to the other device via IoT Hub and a Functions app, then translate it and play the translated speech.
> 💁 Tip: When sending the speech from one device to another, send the language it is in as well, making it easer to translate. You could even have each device register using IoT Hub and a Functions app first, passing the language they support to be stored in Azure Storage. You could then use a Functions app to do the translations, sending the translated text to the IoT device.
## Rubric
| Criteria | Exemplary | Adequate | Needs Improvement |
| -------- | --------- | -------- | ----------------- |
| | | | |
| Create a universal translator | Was able to build a universal translator, converting speech detected by one device into speech played by another device in a different language | Was able to get some components working, such as capturing speech, or translating, but was unable to build the end to end solution | Was unable to build any parts of a working universal translator |

@ -0,0 +1,212 @@
import io
import json
import pyaudio
import requests
import time
import wave
import threading
from azure.iot.device import IoTHubDeviceClient, Message, MethodResponse
from grove.factory import Factory
button = Factory.getButton('GPIO-HIGH', 5)
audio = pyaudio.PyAudio()
microphone_card_number = 1
speaker_card_number = 1
rate = 16000
def capture_audio():
stream = audio.open(format = pyaudio.paInt16,
rate = rate,
channels = 1,
input_device_index = microphone_card_number,
input = True,
frames_per_buffer = 4096)
frames = []
while button.is_pressed():
frames.append(stream.read(4096))
stream.stop_stream()
stream.close()
wav_buffer = io.BytesIO()
with wave.open(wav_buffer, 'wb') as wavefile:
wavefile.setnchannels(1)
wavefile.setsampwidth(audio.get_sample_size(pyaudio.paInt16))
wavefile.setframerate(rate)
wavefile.writeframes(b''.join(frames))
wav_buffer.seek(0)
return wav_buffer
speech_api_key = '<key>'
translator_api_key = '<key>'
location = '<location>'
language = '<language>'
server_language = '<language>'
connection_string = '<connection_string>'
device_client = IoTHubDeviceClient.create_from_connection_string(connection_string)
print('Connecting')
device_client.connect()
print('Connected')
def get_access_token():
headers = {
'Ocp-Apim-Subscription-Key': speech_api_key
}
token_endpoint = f'https://{location}.api.cognitive.microsoft.com/sts/v1.0/issuetoken'
response = requests.post(token_endpoint, headers=headers)
return str(response.text)
def convert_speech_to_text(buffer):
url = f'https://{location}.stt.speech.microsoft.com/speech/recognition/conversation/cognitiveservices/v1'
headers = {
'Authorization': 'Bearer ' + get_access_token(),
'Content-Type': f'audio/wav; codecs=audio/pcm; samplerate={rate}',
'Accept': 'application/json;text/xml'
}
params = {
'language': language
}
response = requests.post(url, headers=headers, params=params, data=buffer)
response_json = json.loads(response.text)
if response_json['RecognitionStatus'] == 'Success':
return response_json['DisplayText']
else:
return ''
def translate_text(text, from_language, to_language):
url = f'https://api.cognitive.microsofttranslator.com/translate?api-version=3.0'
headers = {
'Ocp-Apim-Subscription-Key': translator_api_key,
'Ocp-Apim-Subscription-Region': location,
'Content-type': 'application/json'
}
params = {
'from': from_language,
'to': to_language
}
body = [{
'text' : text
}]
response = requests.post(url, headers=headers, params=params, json=body)
return response.json()[0]['translations'][0]['text']
def get_voice():
url = f'https://{location}.tts.speech.microsoft.com/cognitiveservices/voices/list'
headers = {
'Authorization': 'Bearer ' + get_access_token()
}
response = requests.get(url, headers=headers)
voices_json = json.loads(response.text)
first_voice = next(x for x in voices_json if x['Locale'].lower() == language.lower())
return first_voice['ShortName']
voice = get_voice()
print(f'Using voice {voice}')
playback_format = 'riff-48khz-16bit-mono-pcm'
def get_speech(text):
url = f'https://{location}.tts.speech.microsoft.com/cognitiveservices/v1'
headers = {
'Authorization': 'Bearer ' + get_access_token(),
'Content-Type': 'application/ssml+xml',
'X-Microsoft-OutputFormat': playback_format
}
ssml = f'<speak version=\'1.0\' xml:lang=\'{language}\'>'
ssml += f'<voice xml:lang=\'{language}\' name=\'{voice}\'>'
ssml += text
ssml += '</voice>'
ssml += '</speak>'
response = requests.post(url, headers=headers, data=ssml.encode('utf-8'))
return io.BytesIO(response.content)
def play_speech(speech):
with wave.open(speech, 'rb') as wave_file:
stream = audio.open(format=audio.get_format_from_width(wave_file.getsampwidth()),
channels=wave_file.getnchannels(),
rate=wave_file.getframerate(),
output_device_index=speaker_card_number,
output=True)
data = wave_file.readframes(4096)
while len(data) > 0:
stream.write(data)
data = wave_file.readframes(4096)
stream.stop_stream()
stream.close()
def say(text):
print('Original:', text)
text = translate_text(text, server_language, language)
print('Translated:', text)
speech = get_speech(text)
play_speech(speech)
def announce_timer(minutes, seconds):
announcement = 'Times up on your '
if minutes > 0:
announcement += f'{minutes} minute '
if seconds > 0:
announcement += f'{seconds} second '
announcement += 'timer.'
say(announcement)
def create_timer(total_seconds):
minutes, seconds = divmod(total_seconds, 60)
threading.Timer(total_seconds, announce_timer, args=[minutes, seconds]).start()
announcement = ''
if minutes > 0:
announcement += f'{minutes} minute '
if seconds > 0:
announcement += f'{seconds} second '
announcement += 'timer started.'
say(announcement)
def handle_method_request(request):
payload = json.loads(request.payload)
seconds = payload['seconds']
if seconds > 0:
create_timer(payload['seconds'])
method_response = MethodResponse.create_from_method_request(request, 200)
device_client.send_method_response(method_response)
device_client.on_method_request_received = handle_method_request
while True:
while not button.is_pressed():
time.sleep(.1)
buffer = capture_audio()
text = convert_speech_to_text(buffer)
if len(text) > 0:
print('Original:', text)
text = translate_text(text, language, server_language)
print('Translated:', text)
message = Message(json.dumps({ 'speech': text }))
device_client.send_message(message)

@ -0,0 +1,124 @@
import json
import requests
import threading
import time
from azure.cognitiveservices import speech
from azure.cognitiveservices.speech import SpeechConfig, SpeechRecognizer, SpeechSynthesizer
from azure.cognitiveservices.speech.translation import SpeechTranslationConfig, TranslationRecognizer
from azure.iot.device import IoTHubDeviceClient, Message, MethodResponse
speech_api_key = '<key>'
translator_api_key = '<key>'
location = '<location>'
language = '<language>'
server_language = '<language>'
connection_string = '<connection_string>'
device_client = IoTHubDeviceClient.create_from_connection_string(connection_string)
print('Connecting')
device_client.connect()
print('Connected')
translation_config = SpeechTranslationConfig(subscription=speech_api_key,
region=location,
speech_recognition_language=language,
target_languages=(language, server_language))
recognizer = TranslationRecognizer(translation_config=translation_config)
def recognized(args):
if args.result.reason == speech.ResultReason.TranslatedSpeech:
language_match = next(l for l in args.result.translations if server_language.lower().startswith(l.lower()))
text = args.result.translations[language_match]
if (len(text) > 0):
print(f'Translated text: {text}')
message = Message(json.dumps({ 'speech': text }))
device_client.send_message(message)
recognizer.recognized.connect(recognized)
recognizer.start_continuous_recognition()
speech_config = SpeechTranslationConfig(subscription=speech_api_key,
region=location)
speech_config.speech_synthesis_language = language
speech_synthesizer = SpeechSynthesizer(speech_config=speech_config)
voices = speech_synthesizer.get_voices_async().get().voices
first_voice = next(x for x in voices if x.locale.lower() == language.lower())
speech_config.speech_synthesis_voice_name = first_voice.short_name
def translate_text(text):
url = f'https://api.cognitive.microsofttranslator.com/translate?api-version=3.0'
headers = {
'Ocp-Apim-Subscription-Key': translator_api_key,
'Ocp-Apim-Subscription-Region': location,
'Content-type': 'application/json'
}
params = {
'from': server_language,
'to': language
}
body = [{
'text' : text
}]
response = requests.post(url, headers=headers, params=params, json=body)
return response.json()[0]['translations'][0]['text']
def say(text):
print('Original:', text)
text = translate_text(text)
print('Translated:', text)
ssml = f'<speak version=\'1.0\' xml:lang=\'{language}\'>'
ssml += f'<voice xml:lang=\'{language}\' name=\'{first_voice.short_name}\'>'
ssml += text
ssml += '</voice>'
ssml += '</speak>'
recognizer.stop_continuous_recognition()
speech_synthesizer.speak_ssml(ssml)
recognizer.start_continuous_recognition()
def announce_timer(minutes, seconds):
announcement = 'Times up on your '
if minutes > 0:
announcement += f'{minutes} minute '
if seconds > 0:
announcement += f'{seconds} second '
announcement += 'timer.'
say(announcement)
def create_timer(total_seconds):
minutes, seconds = divmod(total_seconds, 60)
threading.Timer(total_seconds, announce_timer, args=[minutes, seconds]).start()
announcement = ''
if minutes > 0:
announcement += f'{minutes} minute '
if seconds > 0:
announcement += f'{seconds} second '
announcement += 'timer started.'
say(announcement)
def handle_method_request(request):
if request.name == 'set-timer':
payload = json.loads(request.payload)
seconds = payload['seconds']
if seconds > 0:
create_timer(payload['seconds'])
method_response = MethodResponse.create_from_method_request(request, 200)
device_client.send_method_response(method_response)
device_client.on_method_request_received = handle_method_request
while True:
time.sleep(1)

@ -0,0 +1,150 @@
# Translate speech - Raspberry Pi
In this part of the lesson, you will write code to translate text using the translator service.
## Convert text to speech using the translator service
The speech service REST API doesn't support direct translations, instead you can use the Translator service to translate the text generated by the speech to text service, and the text of the spoken response. This service has a REST API you can use to translate the text.
### Task - use the translator resource to translate text
1. Your smart timer will have 2 languages set - the language of the server that was used to train LUIS, and the language spoken by the user. Update the `language` variable to be the language that will be spoken by the used, and add a new variable called `server_language` for the language used to train LUIS:
```python
language = '<user language>'
server_language = '<server language>'
```
Replace `<user language>` with the locale name for language you will be speaking in, for example `fr-FR` for French, or `zn-HK` for Cantonese.
Replace `<server language>` with the locale name for language used to train LUIS.
You can find a list of the supported languages and their locale names in the [Language and voice support documentation on Microsoft docs](https://docs.microsoft.com/azure/cognitive-services/speech-service/language-support?WT.mc_id=academic-17441-jabenn#speech-to-text).
> 💁 If you don't speak multiple languages you can use a service like [Bing Translate](https://www.bing.com/translator) or [Google Translate](https://translate.google.com) to translate from your preferred language to a language of your choice. These services can then play audio of the translated text.
>
> For example, if you train LUIS in English, but want to use French as the user language, you can translate sentences like "set a 2 minute and 27 second timer" from English into French using Bing Translate, then use the **Listen translation** button to speak the translation into your microphone.
>
> ![The listen translation button on Bing translate](../../../images/bing-translate.png)
1. Add the translator API key below the `speech_api_key`:
```python
translator_api_key = '<key>'
```
Replace `<key>` with the API key for your translator service resource.
1. Above the `say` function, define a `translate_text` function that will translate text from the server language to the user language:
```python
def translate_text(text, from_language, to_language):
```
The from and to languages are passed to this function - your app needs to convert from user language to server language when recognizing speech, and from server language to user language when provided spoken feedback.
1. Inside this function, define the URL and headers for the REST API call:
```python
url = f'https://api.cognitive.microsofttranslator.com/translate?api-version=3.0'
headers = {
'Ocp-Apim-Subscription-Key': translator_api_key,
'Ocp-Apim-Subscription-Region': location,
'Content-type': 'application/json'
}
```
The URL for this API is not location specific, instead the location is passed in as a header. The API key is used directly, so unlike the speech service there is no need to get an access token from the token issuer API.
1. Below this define the parameters and body for the call:
```python
params = {
'from': from_language,
'to': to_language
}
body = [{
'text' : text
}]
```
The `params` defines the parameters to pass to the API call, passing the from and to languages. This call will translate text in the `from` language into the `to` language.
The `body` contains the text to translate. This is an array, as multiple blocks of text can be translated in the same call.
1. Make the call the REST API, and get the response:
```python
response = requests.post(url, headers=headers, params=params, json=body)
```
The response that comes back is a JSON array, with one item that contains the translations. This item has an array for translations of all the items passed in the body.
```json
[
{
"translations": [
{
"text": "Set a 2 minute 27 second timer.",
"to": "en"
}
]
}
]
```
1. Return the `test` property from the first translation from the first item in the array:
```python
return response.json()[0]['translations'][0]['text']
```
1. Update the `while True` loop to translate the text from the call to `convert_speech_to_text` from the user language to the server language:
```python
if len(text) > 0:
print('Original:', text)
text = translate_text(text, language, server_language)
print('Translated:', text)
message = Message(json.dumps({ 'speech': text }))
device_client.send_message(message)
```
This code also prints the original and translated versions of the text to the console.
1. Update the `say` function to translate the text to say from the server language to the user language:
```python
def say(text):
print('Original:', text)
text = translate_text(text, server_language, language)
print('Translated:', text)
speech = get_speech(text)
play_speech(speech)
```
This code also prints the original and translated versions of the text to the console.
1. Run your code. Ensure your function app is running, and request a timer in the user language, either by speaking that language yourself, or using a translation app.
```output
pi@raspberrypi:~/smart-timer $ python3 app.py
Connecting
Connected
Using voice fr-FR-DeniseNeural
Original: Définir une minuterie de 2 minutes et 27 secondes.
Translated: Set a timer of 2 minutes and 27 seconds.
Original: 2 minute 27 second timer started.
Translated: 2 minute 27 seconde minute a commencé.
Original: Times up on your 2 minute 27 second timer.
Translated: Chronométrant votre minuterie de 2 minutes 27 secondes.
```
> 💁 Due to the different ways of saying something in different languages, you may get translations that are slightly different to the examples you gave LUIS. If this is the case, add more examples to LUIS, retrain then re-publish the model.
> 💁 You can find this code in the [code/pi](code/pi) folder.
😀 Your multi-lingual timer program was a success!

@ -0,0 +1,190 @@
# Translate speech - Virtual IoT Device
In this part of the lesson, you will write code to translate speech when converting to text using the speech service, then translate text using the Translator service before generating a spoken response.
## Use the speech service to translate speech
The speech service can take speech and not only convert to text in the same language, but also translate the output to other languages.
### Task - use the speech service to translate speech
1. Open the `smart-timer` project in VS Code, and ensure the virtual environment is loaded in the terminal.
1. Add the following import statements below the existing imports:
```python
from azure.cognitiveservices import speech
from azure.cognitiveservices.speech.translation import SpeechTranslationConfig, TranslationRecognizer
import requests
```
This imports classes used to translate speech, and a `requests` library that will be used to make a call to the Translator service later in this lesson.
1. Your smart timer will have 2 languages set - the language of the server that was used to train LUIS, and the language spoken by the user. Update the `language` variable to be the language that will be spoken by the used, and add a new variable called `server_language` for the language used to train LUIS:
```python
language = '<user language>'
server_language = '<server language>'
```
Replace `<user language>` with the locale name for language you will be speaking in, for example `fr-FR` for French, or `zn-HK` for Cantonese.
Replace `<server language>` with the locale name for language used to train LUIS.
You can find a list of the supported languages and their locale names in the [Language and voice support documentation on Microsoft docs](https://docs.microsoft.com/azure/cognitive-services/speech-service/language-support?WT.mc_id=academic-17441-jabenn#speech-to-text).
> 💁 If you don't speak multiple languages you can use a service like [Bing Translate](https://www.bing.com/translator) or [Google Translate](https://translate.google.com) to translate from your preferred language to a language of your choice. These services can then play audio of the translated text. Be aware that the speech recognizer will ignore some audio output from your device, so you may need to use an additional device to play the translated text.
>
> For example, if you train LUIS in English, but want to use French as the user language, you can translate sentences like "set a 2 minute and 27 second timer" from English into French using Bing Translate, then use the **Listen translation** button to speak the translation into your microphone.
>
> ![The listen translation button on Bing translate](../../../images/bing-translate.png)
1. Replace the `recognizer_config` and `recognizer` declarations with the following:
```python
translation_config = SpeechTranslationConfig(subscription=speech_api_key,
region=location,
speech_recognition_language=language,
target_languages=(language, server_language))
recognizer = TranslationRecognizer(translation_config=translation_config)
```
This creates a translation config to recognize speech in the user language, and create translations in the user and server language. It then uses this config to create a translation recognizer - a speech recognizer that can translate the output of the speech recognition into multiple languages.
> 💁 The original language needs to be specified in the `target_languages`, otherwise you won't get any translations.
1. Update the `recognized` function, replacing the entire contents of the function with the following:
```python
if args.result.reason == speech.ResultReason.TranslatedSpeech:
language_match = next(l for l in args.result.translations if server_language.lower().startswith(l.lower()))
text = args.result.translations[language_match]
if (len(text) > 0):
print(f'Translated text: {text}')
message = Message(json.dumps({ 'speech': text }))
device_client.send_message(message)
```
This code checks to see if the recognized event was fired because speech was translated (this event can fire at other times, such as when the speech is recognized but not translated). If the speech was translated, it finds the translation in the `args.result.translations` dictionary that matches the server language.
The `args.result.translations` dictionary is keyed off the language part of the locale setting, not the whole setting. For example, if you request a translation into `fr-FR` for French, the dictionary will contain an entry for `fr`, not `fr-FR`.
The translated text is then sent to the IoT Hub.
1. Run this code to test the translations. Ensure your function app is running, and request a timer in the user language, either by speaking that language yourself, or using a translation app.
```output
(.venv) ➜ smart-timer python app.py
Connecting
Connected
Translated text: Set a timer of 2 minutes and 27 seconds.
```
## Translate text using the translator service
The speech service doesn't support translation pf text back to speech, instead you can use the Translator service to translate the text. This service has a REST API you can use to translate the text.
### Task - use the translator resource to translate text
1. Add the translator API key below the `speech_api_key`:
```python
translator_api_key = '<key>'
```
Replace `<key>` with the API key for your translator service resource.
1. Above the `say` function, define a `translate_text` function that will translate text from the server language to the user language:
```python
def translate_text(text):
```
1. Inside this function, define the URL and headers for the REST API call:
```python
url = f'https://api.cognitive.microsofttranslator.com/translate?api-version=3.0'
headers = {
'Ocp-Apim-Subscription-Key': translator_api_key,
'Ocp-Apim-Subscription-Region': location,
'Content-type': 'application/json'
}
```
The URL for this API is not location specific, instead the location is passed in as a header. The API key is used directly, so unlike the speech service there is no need to get an access token from the token issuer API.
1. Below this define the parameters and body for the call:
```python
params = {
'from': server_language,
'to': language
}
body = [{
'text' : text
}]
```
The `params` defines the parameters to pass to the API call, passing the from and to languages. This call will translate text in the `from` language into the `to` language.
The `body` contains the text to translate. This is an array, as multiple blocks of text can be translated in the same call.
1. Make the call the REST API, and get the response:
```python
response = requests.post(url, headers=headers, params=params, json=body)
```
The response that comes back is a JSON array, with one item that contains the translations. This item has an array for translations of all the items passed in the body.
```json
[
{
"translations": [
{
"text": "Chronométrant votre minuterie de 2 minutes 27 secondes.",
"to": "fr"
}
]
}
]
```
1. Return the `test` property from the first translation from the first item in the array:
```python
return response.json()[0]['translations'][0]['text']
```
1. Update the `say` function to translate the text to say before the SSML is generated:
```python
print('Original:', text)
text = translate_text(text)
print('Translated:', text)
```
This code also prints the original and translated versions of the text to the console.
1. Run your code. Ensure your function app is running, and request a timer in the user language, either by speaking that language yourself, or using a translation app.
```output
(.venv) ➜ smart-timer python app.py
Connecting
Connected
Translated text: Set a timer of 2 minutes and 27 seconds.
Original: 2 minute 27 second timer started.
Translated: 2 minute 27 seconde minute a commencé.
Original: Times up on your 2 minute 27 second timer.
Translated: Chronométrant votre minuterie de 2 minutes 27 secondes.
```
> 💁 Due to the different ways of saying something in different languages, you may get translations that are slightly different to the examples you gave LUIS. If this is the case, add more examples to LUIS, retrain then re-publish the model.
> 💁 You can find this code in the [code/virtual-iot-device](code/virtual-iot-device) folder.
😀 Your multi-lingual timer program was a success!

@ -20,7 +20,9 @@ The projects cover the journey of food from farm to table. This includes farming
![A road map for the course showing 24 lessons covering intro, farming, transport, processing, retail and cooking](sketchnotes/Roadmap.png)
**Hearty thanks to our authors [Jen Fox](https://github.com/jenfoxbot), [Jen Looper](https://github.com/jlooper), [Jim Bennett](https://github.com/jimbobbennett), and sketchnote artist [Nitya Narasimhan](https://github.com/nitya)**
**Hearty thanks to our authors [Jen Fox](https://github.com/jenfoxbot), [Jen Looper](https://github.com/jlooper), [Jim Bennett](https://github.com/jimbobbennett), and our sketchnote artist [Nitya Narasimhan](https://github.com/nitya).**
**Thanks as well to our team of [Microsoft Learn Student Ambassadors](https://studentambassadors.microsoft.com?WT.mc_id=academic-17441-jabenn) who have been reviewing and translating this curriculum - [Aditya Garg](https://github.com/AdityaGarg00), [Aryan Jain](https://www.linkedin.com/in/aryan-jain-47a4a1145/), [Bhavesh Suneja](https://github.com/EliteWarrior315), [Lateefah Bello](https://www.linkedin.com/in/lateefah-bello/), [Manvi Jha](https://github.com/Severus-Matthew), [Mireille Tan](https://www.linkedin.com/in/mireille-tan-a4834819a/), [Mohammad Iftekher (Iftu) Ebne Jalal](https://github.com/Iftu119), [Priyanshu Srivastav](https://www.linkedin.com/in/priyanshu-srivastav-b067241ba), [Thanmai Gowducheruvu](https://github.com/innovation-platform), and [Zina Kamel](https://www.linkedin.com/in/zina-kamel/).**
> **Teachers**, we have [included some suggestions](for-teachers.md) on how to use this curriculum. If you would like to create your own lessons, we have also included a [lesson template](lesson-template/README.md).
@ -83,8 +85,8 @@ We have two choices of IoT hardware to use for the projects depending on persona
| 16 | [Manufacturing](./4-manufacturing) | Check fruit quality from an IoT device | Learn about using your fruit quality detector from an IoT device | [Check fruit quality from an IoT device](./4-manufacturing/lessons/2-check-fruit-from-device/README.md) |
| 17 | [Manufacturing](./4-manufacturing) | Run your fruit detector on the edge | Learn about running your fruit detector on an IoT device on the edge | [Run your fruit detector on the edge](./4-manufacturing/lessons/3-run-fruit-detector-edge/README.md) |
| 18 | [Manufacturing](./4-manufacturing) | Trigger fruit quality detection from a sensor | Learn about triggering fruit quality detection from a sensor | [Trigger fruit quality detection from a sensor](./4-manufacturing/lessons/4-trigger-fruit-detector/README.md) |
| 19 | [Retail](./5-retail) | | |
| 20 | [Retail](./5-retail) | | |
| 19 | [Retail](./5-retail) | Train a stock detector | Learn how to use object detection to train a stock detector to count stock in a shop | [Train a stock detector](./5-retail/lessons/1-train-stock-detector/README.md) |
| 20 | [Retail](./5-retail) | Check stock from an IoT device | Learn how to check stock from an IoT device using an object detection model | [Check stock from an IoT device](./5-retail/lessons/2-check-stock-device/README.md) |
| 21 | [Consumer](./6-consumer) | Recognize speech with an IoT device | Learn how to recognize speech from an IoT device to build a smart timer | [Recognize speech with an IoT device](./6-consumer/lessons/1-speech-recognition/README.md) |
| 22 | [Consumer](./6-consumer) | Understand language | Learn how to understand sentences spoken to an IoT device | [Understand language](./6-consumer/lessons/2-language-understanding/README.md) |
| 23 | [Consumer](./6-consumer) | Set a timer and provide spoken feedback | Learn how to set a timer on an IoT device and give spoken feedback on when the timer is set and when it finishes | [Set a timer and provide spoken feedback](./6-consumer/lessons/3-spoken-feedback/README.md) |

@ -46,7 +46,7 @@ All the device code for Raspberry Pi is in Python. To complete all the assignmen
These are specific to using the Raspberry Pi, and are not relevant to using the Arduino device.
* [Grove Pi base hat](https://wiki.seeedstudio.com/Grove_Base_Hat_for_Raspberry_Pi)
* [Grove Pi base hat](https://www.seeedstudio.com/Grove-Base-Hat-for-Raspberry-Pi.html)
* [Raspberry Pi Camera module](https://www.raspberrypi.org/products/camera-module-v2/)
* Microphone and speaker:

Binary file not shown.

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 15 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 68 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 118 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 11 KiB

File diff suppressed because it is too large Load Diff
Loading…
Cancel
Save