Merge branch 'microsoft:main' into main

pull/114/head
Lateefah Bello 4 years ago committed by GitHub
commit c83724ff7a
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23

1
.gitignore vendored

@ -7,3 +7,4 @@
.vscode/launch.json
.vscode/ipch
.ipynb_checkpoints
/node_modules

@ -1,9 +0,0 @@
# 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!

@ -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>

@ -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.

@ -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.

@ -14,6 +14,8 @@ The main process for getting food from a farmer to a consumer involves loading b
[![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 in transit to ensure drivers are in compliance with local laws on working hours.

@ -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,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.
1. 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:
## Thing 1
```html
<html>
<head>
<style>
#myMap {
width:100%;
height:100%;
}
</style>
</head>
<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 |
| -------- | --------- | -------- | ----------------- |
| | | | |
| -------- | --------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------- | --------------------------------------------------- |
| | 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,48 @@
<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)

@ -6,6 +6,8 @@ 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/41)
@ -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

@ -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,7 +14,7 @@ print('Connecting')
device_client.connect()
print('Connected')
recognizer_config = SpeechConfig(subscription=api_key,
recognizer_config = SpeechConfig(subscription=speech_api_key,
region=location,
speech_recognition_language=language)

@ -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,11 +1,11 @@
import time
from azure.cognitiveservices.speech import SpeechConfig, SpeechRecognizer
api_key = '<key>'
speech_api_key = '<key>'
location = '<location>'
language = '<language>'
recognizer_config = SpeechConfig(subscription=api_key,
recognizer_config = SpeechConfig(subscription=speech_api_key,
region=location,
speech_recognition_language=language)

@ -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,11 +41,11 @@ 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>'
recognizer_config = SpeechConfig(subscription=api_key,
recognizer_config = SpeechConfig(subscription=speech_api_key,
region=location,
speech_recognition_language=language)
```

@ -42,7 +42,7 @@ def capture_audio():
return wav_buffer
api_key = '<key>'
speech_api_key = '<key>'
location = '<location>'
language = '<language>'
connection_string = '<connection_string>'
@ -55,7 +55,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'
@ -97,7 +97,7 @@ def get_voice():
return first_voice['ShortName']
voice = get_voice()
print(f"Using voice {voice}")
print(f'Using voice {voice}')
playback_format = 'riff-48khz-16bit-mono-pcm'
@ -143,10 +143,10 @@ def say(text):
def announce_timer(minutes, seconds):
announcement = 'Times up on your '
if minutes > 0:
announcement += f'{minutes} minute'
announcement += f'{minutes} minute '
if seconds > 0:
announcement += f'{seconds} second'
announcement += ' timer.'
announcement += f'{seconds} second '
announcement += 'timer.'
say(announcement)
def create_timer(total_seconds):
@ -154,10 +154,10 @@ def create_timer(total_seconds):
threading.Timer(total_seconds, announce_timer, args=[minutes, seconds]).start()
announcement = ''
if minutes > 0:
announcement += f'{minutes} minute'
announcement += f'{minutes} minute '
if seconds > 0:
announcement += f'{seconds} second'
announcement += ' timer started.'
announcement += f'{seconds} second '
announcement += 'timer started.'
say(announcement)
def handle_method_request(request):

@ -4,7 +4,7 @@ import time
from azure.cognitiveservices.speech import SpeechConfig, SpeechRecognizer, SpeechSynthesizer
from azure.iot.device import IoTHubDeviceClient, Message, MethodResponse
api_key = '<key>'
speech_api_key = '<key>'
location = '<location>'
language = '<language>'
connection_string = '<connection_string>'
@ -15,7 +15,7 @@ print('Connecting')
device_client.connect()
print('Connected')
recognizer_config = SpeechConfig(subscription=api_key,
recognizer_config = SpeechConfig(subscription=speech_api_key,
region=location,
speech_recognition_language=language)
@ -30,7 +30,7 @@ recognizer.recognized.connect(recognized)
recognizer.start_continuous_recognition()
speech_config = SpeechConfig(subscription=api_key,
speech_config = SpeechConfig(subscription=speech_api_key,
region=location)
speech_config.speech_synthesis_language = language
speech_synthesizer = SpeechSynthesizer(speech_config=speech_config)
@ -53,10 +53,10 @@ def say(text):
def announce_timer(minutes, seconds):
announcement = 'Times up on your '
if minutes > 0:
announcement += f'{minutes} minute'
announcement += f'{minutes} minute '
if seconds > 0:
announcement += f'{seconds} second'
announcement += ' timer.'
announcement += f'{seconds} second '
announcement += 'timer.'
say(announcement)
def create_timer(total_seconds):
@ -64,10 +64,10 @@ def create_timer(total_seconds):
threading.Timer(total_seconds, announce_timer, args=[minutes, seconds]).start()
announcement = ''
if minutes > 0:
announcement += f'{minutes} minute'
announcement += f'{minutes} minute '
if seconds > 0:
announcement += f'{seconds} second'
announcement += ' timer started.'
announcement += f'{seconds} second '
announcement += 'timer started.'
say(announcement)
def handle_method_request(request):

@ -42,7 +42,7 @@ def capture_audio():
return wav_buffer
api_key = '<key>'
speech_api_key = '<key>'
location = '<location>'
language = '<language>'
connection_string = '<connection_string>'
@ -55,7 +55,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'
@ -89,10 +89,10 @@ def say(text):
def announce_timer(minutes, seconds):
announcement = 'Times up on your '
if minutes > 0:
announcement += f'{minutes} minute'
announcement += f'{minutes} minute '
if seconds > 0:
announcement += f'{seconds} second'
announcement += ' timer.'
announcement += f'{seconds} second '
announcement += 'timer.'
say(announcement)
def create_timer(total_seconds):
@ -100,10 +100,10 @@ def create_timer(total_seconds):
threading.Timer(total_seconds, announce_timer, args=[minutes, seconds]).start()
announcement = ''
if minutes > 0:
announcement += f'{minutes} minute'
announcement += f'{minutes} minute '
if seconds > 0:
announcement += f'{seconds} second'
announcement += ' timer started.'
announcement += f'{seconds} second '
announcement += 'timer started.'
say(announcement)
def handle_method_request(request):

@ -4,7 +4,7 @@ import time
from azure.cognitiveservices.speech import SpeechConfig, SpeechRecognizer
from azure.iot.device import IoTHubDeviceClient, Message, MethodResponse
api_key = '<key>'
speech_api_key = '<key>'
location = '<location>'
language = '<language>'
connection_string = '<connection_string>'
@ -15,7 +15,7 @@ print('Connecting')
device_client.connect()
print('Connected')
recognizer_config = SpeechConfig(subscription=api_key,
recognizer_config = SpeechConfig(subscription=speech_api_key,
region=location,
speech_recognition_language=language)
@ -36,10 +36,10 @@ def say(text):
def announce_timer(minutes, seconds):
announcement = 'Times up on your '
if minutes > 0:
announcement += f'{minutes} minute'
announcement += f'{minutes} minute '
if seconds > 0:
announcement += f'{seconds} second'
announcement += ' timer.'
announcement += f'{seconds} second '
announcement += 'timer.'
say(announcement)
def create_timer(total_seconds):
@ -47,10 +47,10 @@ def create_timer(total_seconds):
threading.Timer(total_seconds, announce_timer, args=[minutes, seconds]).start()
announcement = ''
if minutes > 0:
announcement += f'{minutes} minute'
announcement += f'{minutes} minute '
if seconds > 0:
announcement += f'{seconds} second'
announcement += ' timer started.'
announcement += f'{seconds} second '
announcement += 'timer started.'
say(announcement)
def handle_method_request(request):

@ -10,6 +10,8 @@ Each language supports a range of different voices, and you can make a REST requ
### 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
@ -27,7 +29,7 @@ Each language supports a range of different voices, and you can make a REST requ
return first_voice['ShortName']
voice = get_voice()
print(f"Using voice {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.

@ -31,10 +31,10 @@ Timers can be set using the Python `threading.Timer` class. This class takes a d
def announce_timer(minutes, seconds):
announcement = 'Times up on your '
if minutes > 0:
announcement += f'{minutes} minute'
announcement += f'{minutes} minute '
if seconds > 0:
announcement += f'{seconds} second'
announcement += ' timer.'
announcement += f'{seconds} second '
announcement += 'timer.'
say(announcement)
```
@ -55,10 +55,10 @@ Timers can be set using the Python `threading.Timer` class. This class takes a d
```python
announcement = ''
if minutes > 0:
announcement += f'{minutes} minute'
announcement += f'{minutes} minute '
if seconds > 0:
announcement += f'{seconds} second'
announcement += ' timer started.'
announcement += f'{seconds} second '
announcement += 'timer started.'
say(announcement)
```
@ -88,8 +88,8 @@ Timers can be set using the Python `threading.Timer` class. This class takes a d
Connecting
Connected
Set a one minute 4 second timer.
1 minute, 4 second timer started
Times up on your 1 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.

@ -10,6 +10,8 @@ Each language supports a range of different voices, and you can get the list of
### 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
@ -19,7 +21,7 @@ Each language supports a range of different voices, and you can get the list of
1. Above the `say` function, create a speech configuration to use with the speech synthesizer:
```python
speech_config = SpeechConfig(subscription=api_key,
speech_config = SpeechConfig(subscription=speech_api_key,
region=location)
speech_config.speech_synthesis_language = language
speech_synthesizer = SpeechSynthesizer(speech_config=speech_config)

@ -6,30 +6,165 @@ This video gives an overview of the Azure speech services, covering speech to te
[![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/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/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!

@ -22,7 +22,7 @@ The projects cover the journey of food from farm to table. This includes farming
**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 - [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), and [Zina Kamel](https://www.linkedin.com/in/zina-kamel/).**
**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).

@ -0,0 +1,37 @@
- Introduction
- [1](../1-getting-started/lessons/1-introduction-to-iot/README.md)
- [2](../1-getting-started/lessons/2-deeper-dive/README.md)
- [3](../1-getting-started/lessons/3-sensors-and-actuators/README.md)
- [4](../1-getting-started/lessons/4-connect-internet/README.md)
- Farm
- [5](../2-farm/lessons/1-predict-plant-growth/README.md)
- [6](../2-farm/lessons/2-detect-soil-moisture/README.md)
- [7](../2-farm/lessons/3-automated-plant-watering/README.md)
- [8](../2-farm/lessons/4-migrate-your-plant-to-the-cloud/README.md)
- [9](../2-farm/lessons/5-migrate-application-to-the-cloud/README.md)
- [10](../2-farm/lessons/6-keep-your-plant-secure/README.md)
- Transport
- [11](../3-transport/lessons/1-location-tracking/README.md)
- [12](../3-transport/lessons/2-store-location-data/README.md)
- [13](../3-transport/lessons/3-visualize-location-data/README.md)
- [14](../3-transport/lessons/4-geofences/README.md)
- Manufacturing
- [15](../4-manufacturing/lessons/1-train-fruit-detector/README.md)
- [16](../4-manufacturing/lessons/2-check-fruit-from-device/README.md)
- [17](../4-manufacturing/lessons/3-run-fruit-detector-edge/README.md)
- [18](../4-manufacturing/lessons/4-trigger-fruit-detector/README.md)
- Retail
- [19](../5-retail/lessons/1-train-stock-detector/README.md)
- [20](../5-retail/lessons/2-check-stock-device/README.md)
- Consumer
- [21](../6-consumer/lessons/1-speech-recognition/README.md)
- [22](../6-consumer/lessons/2-language-understanding/README.md)
- [23](../6-consumer/lessons/3-spoken-feedback/README.md)
- [24](../6-consumer/lessons/4-multiple-language-support/README.md)

@ -0,0 +1,9 @@
module.exports = {
contents: ['docs/_sidebar.md'], // array of "table of contents" files path
pathToPublic: 'pdf/readme.pdf', // path where pdf will stored
pdfOptions: {
margin: { top: '100px', bottom: '100px' }
}, // reference: https://github.com/GoogleChrome/puppeteer/blob/master/docs/api.md#pagepdfoptions
removeTemp: true, // remove generated .md and .html or not
emulateMedia: 'print', // mediaType, emulating by puppeteer for rendering pdf, 'print' by default (reference: https://github.com/GoogleChrome/puppeteer/blob/master/docs/api.md#pageemulatemediamediatype)
};

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

2251
package-lock.json generated

File diff suppressed because it is too large Load Diff

@ -0,0 +1,28 @@
{
"name": "iot-for-beginners",
"version": "1.0.0",
"description": "IoT for Beginners - A Curriculum",
"main": "index.js",
"scripts": {
"convert": "node_modules/.bin/docsify-to-pdf"
},
"repository": {
"type": "git",
"url": "git+https://github.com/microsoft/IoT-For-Beginners.git"
},
"keywords": [
"iot",
"dev",
"development",
"curriculum"
],
"author": "Jim Bennett and team",
"license": "MIT",
"bugs": {
"url": "https://github.com/microsoft/IoT-For-Beginners/issues"
},
"homepage": "https://github.com/microsoft/IoT-For-Beginners#readme",
"devDependencies": {
"docsify-to-pdf": "0.0.5"
}
}

Binary file not shown.

@ -0,0 +1,9 @@
# माइक्रोसॉफ्ट ओपन सोर्स कोड ऑफ कंडक्ट
इस परियोजना ने [माइक्रोसॉफ्ट ओपन सोर्स कोड ऑफ कंडक्ट](https://opensource.microsoft.com/codeofconduct/) को अपनाया है।
संसाधन:
- [माइक्रोसॉफ्ट ओपन सोर्स कोड ऑफ कंडक्ट](https://opensource.microsoft.com/codeofconduct/)
- [माइक्रोसॉफ्ट कोड ऑफ कंडक्ट के बारे में अक्सर पूछे जाने वाले प्रश्न](https://opensource.microsoft.com/codeofconduct/faq/)
- प्रश्नों या चिंताओं के लिए [openencode@microsoft.com](mailto:openencode@microsoft.com) पे संपर्क करें
Loading…
Cancel
Save