تفعيل التسليم المحلي عمليات الدمج من السحابة الإلكترونية إلى السحابة الإلكترونية

1. قبل البدء

تتيح عمليات الدمج مع الأجهزة المنزلية الذكية لتطبيق "مساعد Google" التحكّم في الأجهزة المتّصلة في منازل المستخدمين. لإنشاء عملية دمج من السحابة إلى السحابة، عليك تقديم نقطة نهاية webhook في السحابة الإلكترونية قادرة على معالجة طلبات المنزل الذكي. على سبيل المثال، عندما يقول أحد المستخدمين "Ok Google، أريد تشغيل الأضواء"، يُرسِل "مساعد Google" الطلب إلى خدمة السحابة الإلكترونية لتعديل حالة الجهاز.

تعمل حزمة تطوير البرامج (SDK) المحلية للمنزل على تحسين عملية الدمج بين "مساعد Google" والمنزل الذكي من خلال إضافة مسار غير مستند إلى السحابة لتوجيه الطلبات المتعلقة بالمنزل الذكي مباشرةً إلى جهاز Google Home، ما يعزّز الموثوقية ويقلل من وقت الاستجابة في معالجة أوامر المستخدمين. يتيح لك هذا الإطار كتابة ونشر تطبيق معالجة طلبات محلي بلغة TypeScript أو JavaScript يحدِّد الأجهزة وينفِّذ الأوامر على أي مكبّر صوت ذكي من Google Home أو شاشة ذكية من Google Nest. يتواصل تطبيقك بعد ذلك مباشرةً مع الأجهزة الذكية الحالية للمستخدمين عبر الشبكة المحلية باستخدام البروتوكولات العادية الحالية لتنفيذ الأوامر.

72ffb320986092c.png

المتطلبات الأساسية

التطبيق الذي ستصممه

في هذا الدليل التعليمي حول رموز البرامج، ستنشر عملية دمج تم إنشاؤها سابقًا للمنزل الذكي باستخدام Firebase، ثم ستطبّق إعدادات مسح ضوئي في وحدة تحكّم المطوّر، وستنشئ تطبيقًا محليًا باستخدام TypeScript لإرسال أوامر مكتوبة بلغة Node.js إلى جهاز غسّالة افتراضي.

ما ستتعرّف عليه

  • كيفية تفعيل ميزة "الاستلام داخل المتجر" وضبطها في Developer Console
  • كيفية استخدام حزمة تطوير البرامج (SDK) المحلية للمنزل لكتابة تطبيق لتنفيذ الإجراءات محليًا
  • كيفية تصحيح أخطاء تطبيق المعالجة المحلية المحمَّل على مكبّر صوت Google Home أو شاشة Google Nest الذكية

المتطلبات

  • أحدث إصدار من Google Chrome
  • جهاز iOS أو Android مزوّد بتطبيق Google Home
  • مكبّر صوت ذكي من Google Home أو شاشة ذكية من Google Nest
  • الإصدار 10.16 من Node.js أو إصدار أحدث
  • حساب Google
  • حساب فوترة على Google Cloud

2. الخطوات الأولى

تفعيل "عناصر التحكّم في النشاط"

لاستخدام "مساعد Google"، عليك مشاركة بيانات نشاط معيّنة مع Google. يحتاج "مساعد Google" إلى هذه البيانات لكي يعمل بشكلٍ سليم، ولكنّ شرط مشاركة البيانات ليس خاصًا بحزمة تطوير البرامج (SDK). لمشاركة هذه البيانات، عليك إنشاء حساب على Google إذا لم يكن لديك حساب. يمكنك استخدام أي حساب على Google، ولا يُشترط أن يكون حساب المطوِّر الخاص بك.

افتح صفحة "عناصر التحكّم في النشاط" لحساب Google الذي تريد استخدامه مع "مساعد Google".

تأكَّد من تفعيل مفاتيح التبديل التالية:

  • النشاط على الويب وفي التطبيقات: بالإضافة إلى ذلك، تأكَّد من وضع علامة في مربّع الاختيار تضمين سجلّ Chrome والأنشطة من المواقع الإلكترونية والتطبيقات والأجهزة التي تستخدم خدمات Google.
  • معلومات الجهاز
  • التفاعل الصوتي مع الجهاز

إنشاء مشروع دمج من السحابة الإلكترونية إلى السحابة الإلكترونية

  1. انتقِل إلى Play Console.
  2. انقر على إنشاء مشروع، وأدخِل اسمًا للمشروع، ثم انقر على إنشاء مشروع.

اسم المشروع

اختيار الدمج من السحابة الإلكترونية إلى السحابة الإلكترونية

في صفحة المشروع الرئيسية في "وحدة تحكّم المطوّر"، اختَر إضافة عملية دمج من السحابة الإلكترونية إلى السحابة الإلكترونية ضمن من السحابة الإلكترونية إلى السحابة الإلكترونية.

إضافة عملية دمج من السحابة الإلكترونية إلى السحابة الإلكترونية

تثبيت Firebase CLI

ستسمح لك واجهة سطر أوامر Firebase (CLI) بعرض تطبيقات الويب محليًا ونشر تطبيق الويب في استضافة Firebase.

لتثبيت واجهة برمجة التطبيقات، شغِّل الأمر npm التالي من الوحدة الطرفية:

npm install -g firebase-tools

للتحقّق من تثبيت واجهة برمجة التطبيقات بشكل صحيح، يمكنك تنفيذ ما يلي:

firebase --version

فوِّض واجهة Firebase CLI باستخدام حسابك على Google من خلال تنفيذ:

firebase login

تفعيل HomeGraph API

تتيح HomeGraph API تخزين الأجهزة وحالاتها وإجراء طلبات بحث عنها ضمن Home Graph الخاص بالمستخدم. لاستخدام واجهة برمجة التطبيقات هذه، عليك أولاً فتح وحدة تحكّم Google Cloud وتفعيل HomeGraph API.

في Google Cloud Console، احرص على اختيار المشروع الذي يتطابق مع <project-id>. عملية الدمج. بعد ذلك، في شاشة "مكتبة واجهات برمجة التطبيقات" لواجهة برمجة التطبيقات HomeGraph API، انقر على تفعيل.

5SVCzM8IZLi_9DV8M0nEklv16NXkpvM0bIzQK2hSyKyvnFHBxPOz90rbr72ayxzmxd5aNROOqC_Cp4outbdlwJdObDs0DIE_8vYzw6dovoVrP9IZWlWsZxDS7UHOi1jiRbDMG8MqUA

3- تشغيل التطبيق النموذجي

بعد إعداد بيئة التطوير، يمكنك نشر المشروع الأوّلي للتأكّد من ضبط كل الإعدادات بشكلٍ صحيح.

الحصول على رمز المصدر

انقر على الرابط التالي لتنزيل نموذج هذا الدليل التعليمي على جهاز التطوير:

...أو يمكنك استنساخ مستودع GitHub من سطر الأوامر:

git clone https://github.com/google-home/smarthome-local.git

لمحة عن المشروع

يحتوي المشروع الأوّلي على الأدلة الفرعية التالية:

  • public: واجهة مستخدم الويب في المقدّمة للتحكّم في الغسالة الذكية ومراقبتها
  • functions—وظائف السحابة الإلكترونية التي تنفِّذ ميزة "الاستيفاء في السحابة الإلكترونية" للدمج بين السحابة الإلكترونية
  • local—مشروع تطبيق skeleton لعرض معلومات عن خدمة التوصيل داخل المتجر مع رمز نموذجي لمعالِج النية في index.ts

تتضمّن ميزة توفير المحتوى من السحابة الإلكترونية الوظائف التالية في index.js:

  • fakeauth—نقطة نهاية التفويض لربط الحسابات
  • faketoken: نقطة نهاية الرمز المميّز لربط الحساب
  • smarthome: نقطة نهاية تنفيذ طلب المنزل الذكي
  • reportstate—يتمّ استدعاء HomeGraph API عند تغيير حالة الجهاز
  • updateDevice: نقطة النهاية المستخدَمة من الجهاز الافتراضي لبدء عملية الإبلاغ عن الحالة

الربط بمنصّة Firebase

انتقِل إلى الدليل app-start، ثمّ أعدّ واجهة Firebase CLI باستخدام مشروع الدمج من السحابة الإلكترونية إلى السحابة الإلكترونية:

cd app-start
firebase use <project-id>

ضبط مشروع Firebase

ابدأ مشروعًا على Firebase.

firebase init

اختَر ميزات سطر الأوامر وقاعدة البيانات الآنية الاستجابة والدوالّ وميزة الاستضافة التي تتضمّن "استضافة Firebase".

? Which Firebase CLI features do you want to set up for this directory? Press Space to select features, then
 Enter to confirm your choices.
❯◉ Realtime Database: Configure a security rules file for Realtime Database and (optionally) provision default instance
 ◯ Firestore: Configure security rules and indexes files for Firestore
 ◉ Functions: Configure a Cloud Functions directory and its files
 ◉ Hosting: Configure files for Firebase Hosting and (optionally) set up GitHub Action deploys
 ◯ Hosting: Set up GitHub Action deploys
 ◯ Storage: Configure a security rules file for Cloud Storage
 ◯ Emulators: Set up local emulators for Firebase products
 ◯ Remote Config: Configure a template file for Remote Config
 ◯ Extensions: Set up an empty Extensions manifest

سيؤدي ذلك إلى بدء واجهات برمجة التطبيقات والميزات اللازمة لمشروعك.

ابدأ قاعدة بيانات Realtime Database عندما يُطلب منك ذلك. يمكنك استخدام الموقع الجغرافي التلقائي لمثيل قاعدة البيانات.

? It seems like you haven't initialized Realtime Database in your project yet. Do you want to set it up?
Yes

? Please choose the location for your default Realtime Database instance:
us-central1

بما أنّك تستخدم رمز المشروع الأوّلي، اختَر الملف التلقائي لقواعد الأمان، وتأكَّد من عدم استبدال ملف قواعد قاعدة البيانات الحالي.

? File database.rules.json already exists. Do you want to overwrite it with the Realtime Database Security Rules for <project-ID>-default-rtdb from the Firebase Console?
No

إذا كنت بصدد إعادة بدء مشروعك، اختَر استبدال عندما يُطلب منك تحديد ما إذا كنت تريد بدء قاعدة بيانات أو استبدالها.

? Would you like to initialize a new codebase, or overwrite an existing one?
Overwrite

عند ضبط Functions، يجب استخدام الملفات التلقائية والتأكّد من عدم استبدال الملفَين الحاليَين index.js وpackage.json في نموذج المشروع.

? What language would you like to use to write Cloud Functions?
JavaScript

? Do you want to use ESLint to catch probable bugs and enforce style?
No

? File functions/package.json already exists. Overwrite?
No

? File functions/index.js already exists. Overwrite?
No

إذا كنت بصدد إعادة بدء مشروعك، اختَر لا عندما يُطلب منك تحديد ما إذا كنت تريد بدء أو استبدال functions/.gitignore.

? File functions/.gitignore already exists. Overwrite?
No
? Do you want to install dependencies with npm now?
Yes

أخيرًا، اضبط إعدادات الاستضافة لاستخدام دليل public في رمز المشروع، واستخدِم الملف الحالي index.html. اختَر لا عندما يُطلب منك استخدام ESLint.

? What do you want to use as your public directory?
public

? Configure as a single-page app (rewrite all urls to /index.html)?
Yes

? Set up automatic builds and deploys with GitHub?
No

? File public/index.html already exists. Overwrite?
 No

إذا تم تفعيل ESLint عن طريق الخطأ، تتوفّر طريقتان لإيقافه:

  1. باستخدام واجهة المستخدم الرسومية، انتقِل إلى مجلد ../functions ضمن المشروع، واختَر الملف المخفي .eslintrc.js واحذِفه. لا تخلط بينه وبين .eslintrc.json الذي يحمل اسمًا مشابهًا.
  2. باستخدام سطر الأوامر:
    cd functions
    rm .eslintrc.js
    

لضمان توفُّر إعدادات Firebase صحيحة وكاملة، انسخ ملف firebase.json من الدليل washer-done إلى الدليل washer-start، مع استبدال الملف المتوفّر في washer-start.

في دليل washer-start:

cp -vp ../washer-done/firebase.json .

النشر على Firebase

بعد تثبيت التبعيات وضبط مشروعك، أصبحت جاهزًا لتشغيل التطبيق للمرّة الأولى.

firebase deploy

في ما يلي نتائج وحدة التحكّم التي من المفترض أن تظهر لك:

...

✔ Deploy complete!

Project Console: https://console.firebase.google.com/project/<project-id>/overview
Hosting URL: https://<project-id>.web.app

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

افتح عنوان URL للاستضافة في المتصفّح (https://<project-id>.web.app) لعرض تطبيق الويب. ستظهر لك الواجهة التالية:

L60eA7MOnPmbBMl2XMipT9MdnP-RaVjyjf0Y93Y1b7mEyIsqZrrwczE7D3RQISRs-iusL1g4XbNmGhuA6-5sLcWefnczwNJEPfNLtwBsO4Tb9YvcAZBI6_rX19z8rxbik9Vq8F2fwg

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

حان الآن وقت ربط خدمة السحابة الإلكترونية التي تم نشرها بخدمة "مساعد Google" باستخدام وحدة تحكّم المطوّر.

ضبط مشروعك على Developer Console

في علامة التبويب تطوير، أضِف اسمًا معروضًا للتفاعل. سيظهر هذا الاسم في تطبيق Google Home.

إضافة اسم معروض

ضمن علامة التطبيق التجارية، حمِّل ملف png لرمز التطبيق بحجم 144 × 144 بكسل واسمه .png.

إضافة رمز تطبيق

لتفعيل ميزة ربط الحساب، استخدِم إعدادات ربط الحساب التالية:

معرِّف العميل

ABC123

سر العميل

DEF456

عنوان URL للترخيص

https://us-central1-
.cloudfunctions.net/fakeauth

عنوان URL للرمز المميّز

https://us-central1-
.cloudfunctions.net/faketoken

تعديل عناوين URL لربط الحساب

ضمن عنوان URL لتنفيذ الإجراءات في السحابة الإلكترونية، أدخِل عنوان URL لوظيفة السحابة الإلكترونية التي توفّر إجراءات تنفيذ طلبات المنزل الذكي.

https://us-central1--cloudfunctions.net/smarthome

إضافة عنوان URL للدالة السحابية

انقر على حفظ لحفظ إعدادات مشروعك، ثمّ انقر على التالي: اختبار لتفعيل الاختبار في مشروعك.

اختبار عملية الدمج من السحابة الإلكترونية إلى السحابة الإلكترونية

يمكنك الآن البدء في تنفيذ وحدات ربط الويب اللازمة لربط حالة الجهاز بخدمة "مساعد Google".

لاختبار عملية الدمج من السحابة الإلكترونية إلى السحابة الإلكترونية، عليك ربط مشروعك بحساب Google. يتيح ذلك إجراء الاختبار من خلال مساحات عرض "مساعد Google" وتطبيق Google Home اللذَين تم تسجيل الدخول إلى الحساب نفسه من خلالهما.

  1. على هاتفك، افتح إعدادات "مساعد Google". يُرجى العلم أنّه يجب تسجيل الدخول باستخدام الحساب نفسه المستخدَم في وحدة التحكّم.
  2. انتقِل إلى مساعد Google > الإعدادات > التحكّم في المنزل (ضمن "مساعد Google").
  3. انقر على رمز البحث في أعلى يسار الصفحة.
  4. ابحث عن تطبيقك التجريبي باستخدام البادئة [test] للعثور على تطبيقك التجريبي المحدّد.
  5. اختَر هذا العنصر. سيصلك بعد ذلك طلب من "مساعد Google" لإثبات هويتك من خلال خدمتك، وسيطلب من خدمتك تقديم قائمة بالأجهزة للمستخدم.SYNC

افتح تطبيق Google Home وتأكَّد من ظهور غسّالة الملابس.

XcWmBVamBZtPfOFqtsr5I38stPWTqDcMfQwbBjetBgxt0FCjEs285pa9K3QXSASptw0KYN2G8yfkT0-xg664V4PjqMreDDs-HPegHjOc4EVtReYPu-WKZyygq9Xmkf8X8z9177nBjQ

تأكَّد من أنّه يمكنك التحكّم في الغسالة باستخدام الطلبات الصوتية في تطبيق Google Home. من المفترض أيضًا أن تلاحظ تغيير حالة الجهاز في واجهة المستخدم على الويب لخدمة الربط بالسحابة الإلكترونية.

يمكنك الآن البدء بإضافة ميزة التوصيل داخل المتجر إلى عملية الدمج.

4. تعديل التسليم في السحابة الإلكترونية

لإتاحة التسليم المحلي، عليك إضافة حقل جديد لكل جهاز يُسمى otherDeviceIds إلى استجابة SYNC في السحابة الإلكترونية يحتوي على معرّف محلي فريد للجهاز. يشير هذا الحقل أيضًا إلى إمكانية التحكّم في هذا الجهاز محليًا.

أضِف الحقل otherDeviceIds إلى استجابة SYNC كما هو موضّح في مقتطف الرمز البرمجي التالي:

functions/index.js

app.onSync((body) => {
  return {
    requestId: body.requestId,
    payload: {
      agentUserId: '123',
      devices: [{
        id: 'washer',
        type: 'action.devices.types.WASHER',
        traits: [ ... ],
        name: { ... },
        deviceInfo: { ... },
        willReportState: true,
        attributes: {
          pausable: true,
        },
        otherDeviceIds: [{
          deviceId: 'deviceid123',
        }],
      }],
    },
  };
});

يمكنك نشر المشروع المعدَّل على Firebase باتّباع الخطوات التالية:

firebase deploy --only functions

بعد اكتمال عملية النشر، انتقِل إلى واجهة مستخدم الويب وانقر على الزر إعادة تحميل ae8d3b25777a5e30.png في شريط الأدوات. يؤدي ذلك إلى بدء عملية "مزامنة الطلبات" حتى يتلقّى "مساعد Google" بيانات ردّ SYNC المعدَّلة.

bf4f6a866160a982.png

5- ضبط إعدادات التوصيل داخل المتجر

في هذا القسم، ستضيف خيارات الضبط اللازمة للتسليم داخل المتجر إلى عملية الدمج من السحابة إلى السحابة. أثناء التطوير، ستنشر تطبيق المعالجة المحلية على "استضافة Firebase"، حيث يمكن لجهاز Google Home الوصول إليه وتنزيله.

في Developer Console، اختَر تطوير > الإجراءات وابحث عن قسم ضبط حزمة تطوير البرامج (SDK) المحلية للجهاز. أدخِل عنوان URL التالي في حقل عنوان URL التجريبي، وأدخِل رقم تعريف مشروعك، ثم انقر على حفظ:

https://<project-id>.web.app/local-home/index.html

7d59b31f8d2a988.png

بعد ذلك، علينا تحديد كيفية اكتشاف جهاز Google Home للأجهزة الذكية المحلية. تتوافق منصة Local Home مع العديد من البروتوكولات لاكتشاف الأجهزة، بما في ذلك mDNS وUPnP وبث UDP. ستستخدم بث UDP لاكتشاف الغسالة الذكية.

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

الحقل

الوصف

القيمة المقترَحة

عنوان البث

عنوان البث العام لبروتوكول UDP

255.255.255.255

منفذ البث

المنفذ الذي يُرسِل من خلاله Google Home بث UDP

3311

منفذ الاستماع

المنفذ الذي يستمع فيه Google Home إلى الاستجابة

3312

حزمة الاستكشاف

حمولة بيانات البث عبر بروتوكول UDP

48656c6c6f4c6f63616c486f6d6553444b

4777bf63c53b6858.png

أخيرًا، انقر على حفظ في أعلى النافذة لنشر التغييرات.

6- تنفيذ ميزة "تلبية الطلبات داخل المتجر"

ستطوّر تطبيقك المخصّص للتنفيذ المحلي بلغة TypeScript باستخدام حزمة typings لحزمة Local Home SDK. اطّلِع على الهيكل المقدَّم في المشروع الأوّلي:

local/index.ts

/// <reference types="@google/local-home-sdk" />

import App = smarthome.App;
import Constants = smarthome.Constants;
import DataFlow = smarthome.DataFlow;
import Execute = smarthome.Execute;
import Intents = smarthome.Intents;
import IntentFlow = smarthome.IntentFlow;

...

class LocalExecutionApp {

  constructor(private readonly app: App) { }

  identifyHandler(request: IntentFlow.IdentifyRequest):
      Promise<IntentFlow.IdentifyResponse> {
    // TODO: Implement device identification
  }

  executeHandler(request: IntentFlow.ExecuteRequest):
      Promise<IntentFlow.ExecuteResponse> {
    // TODO: Implement local fulfillment
  }

  ...
}

const localHomeSdk = new App('1.0.0');
const localApp = new LocalExecutionApp(localHomeSdk);
localHomeSdk
  .onIdentify(localApp.identifyHandler.bind(localApp))
  .onExecute(localApp.executeHandler.bind(localApp))
  .listen()
  .then(() => console.log('Ready'))
  .catch((e: Error) => console.error(e));

وتمثل فئة smarthome.App المكوّن الأساسي لعملية توصيل الطلبات داخل المتجر. يربط المشروع المبدئي معالِجات لطلبَي IDENTIFY وEXECUTE، ثم يستدعي الطريقة listen() لإعلام حزمة Local Home SDK بأنّ التطبيق جاهز.

إضافة معالِج IDENTIFY

تبدأ حزمة SDK لتطبيق Home على الأجهزة المحلية في تشغيل معالِج IDENTIFY عندما يكتشف جهاز Google Home أجهزة لم يتم إثبات ملكيتها على الشبكة المحلية استنادًا إلى إعدادات الفحص المقدَّمة في "وحدة تحكّم المطوّر".

وفي الوقت نفسه، تستدعي المنصة identifyHandler باستخدام بيانات المسح الناتجة عندما تكتشف Google جهازًا مطابقًا. في تطبيقك، يتم إجراء عملية المسح الضوئي باستخدام بث UDP، وتشمل بيانات المسح الضوئي المقدَّمة إلى معالِج IDENTIFY بيانات الإرسال التي أرسلها الجهاز المحلي.

يعرض معالِج الأحداث مثيل IdentifyResponse يحتوي على معرّف فريد للجهاز المحلي. أضِف الرمز التالي إلى طريقة identifyHandler لمعالجة استجابة بروتوكول UDP الواردة من الجهاز المحلي وتحديد رقم تعريف الجهاز المحلي المناسب:

local/index .ts

identifyHandler(request: IntentFlow.IdentifyRequest):
    Promise<IntentFlow.IdentifyResponse> {
  console.log("IDENTIFY intent: " + JSON.stringify(request, null, 2));

  const scanData = request.inputs[0].payload.device.udpScanData;
  if (!scanData) {
    const err = new IntentFlow.HandlerError(request.requestId,
        'invalid_request', 'Invalid scan data');
    return Promise.reject(err);
  }

  // In this codelab, the scan data contains only local device id.
  const localDeviceId = Buffer.from(scanData.data, 'hex');

  const response: IntentFlow.IdentifyResponse = {
    intent: Intents.IDENTIFY,
    requestId: request.requestId,
    payload: {
      device: {
        id: 'washer',
        verificationId: localDeviceId.toString(),
      }
    }
  };
  console.log("IDENTIFY response: " + JSON.stringify(response, null, 2));

  return Promise.resolve(response);
}

يُرجى العلم أنّه يجب أن يتطابق حقل verificationId مع إحدى قيم otherDeviceIds في استجابة SYNC، ما يشير إلى أنّ الجهاز متوفّر للتوصيل داخل المتجر في Home Graph الخاص بالمستخدم. بعد أن تعثر Google على مطابقة، يُعتبر هذا الجهاز تم إثبات ملكيته وجاهزًا للتسليم داخل المتجر.

أضِف معالِج EXECUTE.

تبدأ حزمة تطوير البرامج (SDK) المحلية للمنزل في تشغيل معالِج EXECUTE عندما يتلقّى جهاز متوافق مع ميزة "التشغيل على الجهاز فقط" أمرًا. يعادل محتوى النية المحلية نية EXECUTE المُرسَلة إلى عملية المعالجة في السحابة الإلكترونية، لذا فإنّ منطق معالجة النية محليًا يشبه طريقة معالجتها في السحابة الإلكترونية.

يمكن للتطبيق استخدام مقابس TCP/UDP أو طلبات HTTP(S) للتواصل مع الأجهزة المحلية. في هذا الدليل التعليمي حول الرموز البرمجية، يُستخدَم بروتوكول HTTP للتحكّم في الجهاز الافتراضي. يتم تحديد رقم المنفذ في index.ts على أنّه المتغيّر SERVER_PORT.

أضِف الرمز التالي إلى طريقة executeHandler لمعالجة الأوامر الواردة وإرسالها إلى الجهاز المحلي عبر HTTP:

local/index.ts

executeHandler(request: IntentFlow.ExecuteRequest):
    Promise<IntentFlow.ExecuteResponse> {
  console.log("EXECUTE intent: " + JSON.stringify(request, null, 2));

  const command = request.inputs[0].payload.commands[0];
  const execution = command.execution[0];
  const response = new Execute.Response.Builder()
    .setRequestId(request.requestId);

  const promises: Array<Promise<void>> = command.devices.map((device) => {
    console.log("Handling EXECUTE intent for device: " + JSON.stringify(device));

    // Convert execution params to a string for the local device
    const params = execution.params as IWasherParams;
    const payload = this.getDataForCommand(execution.command, params);

    // Create a command to send over the local network
    const radioCommand = new DataFlow.HttpRequestData();
    radioCommand.requestId = request.requestId;
    radioCommand.deviceId = device.id;
    radioCommand.data = JSON.stringify(payload);
    radioCommand.dataType = 'application/json';
    radioCommand.port = SERVER_PORT;
    radioCommand.method = Constants.HttpOperation.POST;
    radioCommand.isSecure = false;

    console.log("Sending request to the smart home device:", payload);

    return this.app.getDeviceManager()
      .send(radioCommand)
      .then(() => {
        const state = {online: true};
        response.setSuccessState(device.id, Object.assign(state, params));
        console.log(`Command successfully sent to ${device.id}`);
      })
      .catch((e: IntentFlow.HandlerError) => {
        e.errorCode = e.errorCode || 'invalid_request';
        response.setErrorState(device.id, e.errorCode);
        console.error('An error occurred sending the command', e.errorCode);
      });
  });

  return Promise.all(promises)
    .then(() => {
      return response.build();
    })
    .catch((e) => {
      const err = new IntentFlow.HandlerError(request.requestId,
          'invalid_request', e.message);
      return Promise.reject(err);
    });
}

تجميع تطبيق TypeScript

انتقِل إلى الدليل local/ ونفِّذ الأوامر التالية لتنزيل مترجم TypeScript وتجميع التطبيق:

cd local
npm install
npm run build

يؤدي ذلك إلى تجميع مصدر index.ts (TypeScript) ووضع المحتوى التالي في الدليل public/local-home/:

  • bundle.js: ناتج JavaScript المجمَّع الذي يحتوي على التطبيق المحلي والملفات المضمّنة
  • index.html: صفحة الاستضافة المحلية المستخدَمة لعرض التطبيق من أجل الاختبار على الجهاز

نشر المشروع التجريبي

يمكنك نشر ملفات المشروع المعدَّلة على Firebase Hosting حتى تتمكّن من الوصول إليها من جهاز Google Home.

firebase deploy --only hosting

7- تشغيل الغسالة الذكية

حان الآن وقت اختبار الاتّصال بين تطبيق التسليم المحلي والغسّالة الذكية. يتضمّن مشروع Codelab المبتدئ غسّالة ذكية افتراضية مكتوبة بلغة Node.js تحاكي غسّالة ذكية يمكن للمستخدمين التحكّم فيها محليًا.

ضبط الجهاز

عليك ضبط الجهاز الافتراضي لاستخدام مَعلمات بروتوكول UDP نفسها التي طبّقتها على إعدادات المسح لاكتشاف الأجهزة في "وحدة تحكّم المطوّر". بالإضافة إلى ذلك، عليك إخبار الجهاز الافتراضي برقم تعريف الجهاز المحلي المطلوب الإبلاغ عنه ورقم تعريف مشروع الدمج من السحابة إلى السحابة المطلوب استخدامه لأحداث الإبلاغ عن الحالة عند تغيُّر حالة الجهاز.

المعلَمة

القيمة المقترَحة

deviceId

deviceid123

discoveryPortOut

3311

discoveryPacket

HelloLocalHomeSDK

projectId

رقم تعريف مشروع الدمج من السحابة الإلكترونية إلى السحابة الإلكترونية

تشغيل الجهاز

انتقِل إلى الدليل virtual-device/ وشغِّل النص البرمجي للجهاز، مع تمرير مَعلمات الضبط كوسيطات:

cd virtual-device
npm install
npm start -- \
  --deviceId=deviceid123 --projectId=<project-id> \
  --discoveryPortOut=3311 --discoveryPacket=HelloLocalHomeSDK

تأكَّد من تشغيل نص الجهاز البرمجي باستخدام المَعلمات المتوقّعة:

(...): UDP Server listening on 3311
(...): Device listening on port 3388
(...): Report State successful

8. تصحيح أخطاء تطبيق TypeScript

في القسم التالي، عليك التأكّد من أنّ جهاز Google Home يمكنه فحص الغسّالة الذكية الافتراضية وتحديدها وإرسال الأوامر إليها بشكل صحيح عبر الشبكة المحلية. يمكنك استخدام أدوات مطوّري برامج Google Chrome للاتصال بجهاز Google Home وعرض سجلّات وحدة التحكّم وتصحيح أخطاء تطبيق TypeScript.

ربط أدوات مطوّري برامج Chrome

لربط أداة تصحيح الأخطاء بتطبيقك المخصّص للتنفيذ على الجهاز، اتّبِع الخطوات التالية:

  1. تأكَّد من ربط جهاز Google Home بمستخدم لديه إذن بالوصول إلى مشروع Developer Console.
  2. يُرجى إعادة تشغيل جهاز Google Home، ما يتيح له الحصول على عنوان URL لملف HTML بالإضافة إلى إعدادات الفحص التي وضعتها في Developer Console.
  3. افتح Chrome على جهاز التطوير.
  4. افتح علامة تبويب جديدة في Chrome وأدخِل chrome://inspect في حقل العنوان لتشغيل أداة الفحص.

من المفترض أن تظهر لك قائمة بالأجهزة في الصفحة، ويجب أن يظهر عنوان URL لتطبيقك ضمن اسم جهاز Google Home.

567f97789a7d8846.png

افتح أداة الفحص.

انقر على فحص ضمن عنوان URL لتطبيقك لبدء تشغيل "أدوات مطوّري برامج Chrome". اختَر علامة التبويب وحدة التحكّم وتأكَّد من أنّه يمكنك الاطّلاع على محتوى طلب IDENTIFY الذي يطبعه تطبيق TypeScript.

6b67ded470a4c8be.png

تشير هذه النتيجة إلى أنّ تطبيق الربط المحلي قد اكتشف الجهاز الافتراضي وحدَّده بنجاح.

اختبار خدمة التوصيل داخل المتجر

يمكنك إرسال الطلبات إلى جهازك باستخدام عناصر التحكّم باللمس في تطبيق Google Home أو من خلال الطلبات الصوتية إلى جهاز Google Home، مثل:

"Ok Google، أريد تشغيل غسّالتي".

"Ok Google، أريد تشغيل غسّالتي".

"Ok Google، أوقِف غسّالتي".

من المفترض أن يؤدي ذلك إلى حثّ المنصة على إرسال طلب EXECUTE إلى تطبيق TypeScript.

bc030517dacc3ac9.png

تأكَّد من أنّه يمكنك رؤية تغيير حالة الغسالة الذكية المحلية مع كل أمر.

...
***** The washer is RUNNING *****
...
***** The washer is STOPPED *****

9. تهانينا

764dbc83b95782a.png

تهانينا! إذا كنت قد استخدمت حزمة تطوير البرامج (SDK) المحلية للمنزل لدمج ميزة "الاستجابة بدون اتصال بالإنترنت" في عملية دمج من السحابة إلى السحابة

مزيد من المعلومات

في ما يلي بعض الإجراءات الإضافية التي يمكنك تجربتها:

  • غيِّر إعدادات البحث وفعِّله. على سبيل المثال، جرِّب استخدام منفذ UDP أو حزمة اكتشاف مختلفة.
  • عدِّل قاعدة بيانات الجهاز الذكي الافتراضي لتشغيلها على جهاز مضمّن، مثل Raspberry Pi، واستخدِم مصابيح LED أو شاشة لعرض الحالة الحالية.