1- قبل البدء
تستخدم الإجراءات المنزلية الذكية أنواع الأجهزة للسماح لخدمة "مساعد Google" بمعرفة القواعد النحوية التي يجب استخدامها مع الجهاز. تحدد سمات الجهاز إمكانات نوع الجهاز. ويكتسب الجهاز حالات كل سمة جهاز تتم إضافتها إلى الإجراء.
يمكنك ربط أي سمات متوافقة بنوع الجهاز الذي اخترته لتخصيص وظائف أجهزة المستخدمين. إذا كنت تريد تطبيق سمات مخصّصة في الإجراءات وهي غير متوفّرة حاليًا في مخطط الجهاز، تتيح السمتان الأوضاع والتبديل إمكانية التحكّم في إعدادات معيّنة باستخدام اسم مخصّص تحدّده.
بالإضافة إلى إمكانية التحكّم الأساسية التي توفّرها الأنواع والسمات، تتضمّن Smart Home API ميزات إضافية لتحسين تجربة المستخدم. توفّر الردود الواردة عن الخطأ ملاحظات تفصيلية للمستخدم في حال عدم نجاح الأغراض. وتعمل ميزة "التحقّق الثانوي" من المستخدم على توسيع نطاق هذه الاستجابات وإضافة مستوى أمان إضافي إلى سمة الجهاز التي تختارها. من خلال إرسال ردود محدّدة حول طلبات حظر المحتوى الموجّهة إلى "مساعد Google"، يمكن أن يتطلّب إجراء المنزل المزوّد بأجهزة ذكية إذنًا إضافيًا لإكمال الطلب.
المتطلبات الأساسية
- دليل مطوِّر المهام المخصّصة للمنزل المزوّد بأجهزة ذكية
- الدرس التطبيقي حول ترميز الغسّالات المنزلية الذكية
- دليل المطوِّر عن أنواع الأجهزة وسماتها
ما ستقوم بإنشائه
في هذا الدرس التطبيقي حول الترميز، ستعمل على دمج المنزل المزوّد بأجهزة ذكية مسبقًا مع Firebase، ثم ستتعلّم كيفية إضافة سمات غير عادية إلى غسّالة المنزل المزوّد بأجهزة ذكية من أجل حجم التحميل ووضع Turbo. وعليك أيضًا تنفيذ عملية الإبلاغ عن الأخطاء والاستثناءات، كما ستتعلّم كيفية فرض إقرار شفهي لتشغيل الغسّالة باستخدام نموذج التحقّق الثانوي من المستخدِم.
ما ستتعرَّف عليه
- طريقة إضافة السمتَين "الأوضاع" و"التبديل" إلى الإجراء
- كيفية الإبلاغ عن الأخطاء والاستثناءات
- كيفية تطبيق الطريقة الثانوية لإثبات هوية المستخدِم
المتطلبات
- متصفح ويب، مثل Google Chrome
- جهاز iOS أو Android تم تثبيت تطبيق Google Home عليه
- الإصدار 10.16 من Node.js أو إصدار أحدث
- حساب Google
- حساب فوترة على Google Cloud
2- الخطوات الأولى
تفعيل عناصر التحكم في النشاط
لاستخدام "مساعد Google"، يجب مشاركة بيانات نشاط معيّنة مع Google. ويحتاج "مساعد Google" إلى هذه البيانات ليعمل بشكل صحيح، إلا أنّ شرط مشاركة البيانات لا يقتصر على حزمة تطوير البرامج (SDK). لمشاركة هذه البيانات، أنشِئ حسابًا على Google إذا لم يكن لديك حساب. يمكنك استخدام أي حساب على Google، وليس بالضرورة أن يكون حساب المطوِّر.
افتح صفحة عناصر التحكّم في النشاط لحساب Google الذي تريد استخدامه مع "مساعد Google".
تأكّد من أنّ مفاتيح التبديل التالية مفعَّلة:
- النشاط على الويب وفي التطبيقات: بالإضافة إلى ذلك، احرص على وضع علامة في مربّع الاختيار تضمين سجلّ Chrome والأنشطة من المواقع والتطبيقات والأجهزة التي تستخدم خدمات Google.
- معلومات الجهاز
- التفاعل الصوتي مع الجهاز
إنشاء مشروع "المهام"
- انتقِل إلى الإجراءات على Google Developer Console.
- انقر على مشروع جديد، وأدخِل اسمًا للمشروع، ثمّ انقر على إنشاء مشروع.
يُرجى النقر على تطبيق المنزل المزوّد بأجهزة ذكية.
في شاشة "نظرة عامة" في "وحدة تحكّم الإجراءات"، اختَر منزل مزوّد بأجهزة ذكية.
اختَر بطاقة تجربة المنزل المزوّد بأجهزة ذكية وانقر على بدء البناء، وسيتم توجيهك بعد ذلك إلى وحدة تحكّم المشروع.
تثبيت واجهة سطر الأوامر في Firebase
ستتيح لك واجهة سطر أوامر Firebase (CLI) عرض تطبيقات الويب محليًا ونشر تطبيق الويب على استضافة Firebase.
لتثبيت واجهة سطر الأوامر، قم بتشغيل الأمر npm التالي من الوحدة الطرفية:
npm install -g firebase-tools
للتحقّق من أنّه تم تثبيت واجهة سطر الأوامر بشكل صحيح، شغِّل:
firebase --version
يمكنك تفويض واجهة سطر الأوامر في Firebase باستخدام حسابك على Google من خلال تشغيل:
firebase login
تفعيل HomeGraph API
تتيح HomeGraph API إمكانية تخزين الأجهزة وحالاتها وإجراء طلبات بحث عنها ضمن Home Graph للمستخدم. لاستخدام واجهة برمجة التطبيقات هذه، عليك أولاً فتح وحدة تحكُّم Google Cloud وتفعيل HomeGraph API.
في وحدة تحكُّم Google Cloud، تأكَّد من اختيار المشروع الذي يتطابق مع الإجراءات الخاصة بك <project-id>.
. بعد ذلك، انقر على تفعيل في شاشة "مكتبة واجهة برمجة التطبيقات" الخاصة بواجهة HomeGraph API.
3- تشغيل تطبيق المبتدئين
الآن وبعد إعداد بيئة التطوير، يمكنك نشر المشروع المبدئي للتحقق من ضبط كل شيء بشكل صحيح.
الحصول على رمز المصدر
انقر على الرابط التالي لتنزيل نموذج هذا الدرس التطبيقي حول الترميز على جهاز التطوير الذي تستخدمه:
...أو يمكنك استنساخ مستودع جيت هب من سطر الأوامر:
git clone https://github.com/google-home/smarthome-traits.git
فُكَّ حزمة ملف ZIP الذي تم تنزيله.
لمحة عن المشروع
يحتوي المشروع الأوّلي على الأدلة الفرعية التالية:
public:
واجهة مستخدم أمامية للتحكّم بسهولة في حالة الغسّالة الذكية ومراقبتهاfunctions:
هي خدمة سحابية يتم تنفيذها بالكامل وتدير الغسّالة الذكية باستخدام وظائف Cloud لمنصة Firebase و"قاعدة بيانات Firebase في الوقت الفعلي".
يتضمن توفير السحابة الإلكترونية الوظائف التالية في index.js
:
fakeauth
: نقطة نهاية التفويض لربط الحسابfaketoken
: نقطة نهاية الرمز المميّز لربط الحسابsmarthome
: نقطة النهاية لتنفيذ هدف المنزل المزوّد بأجهزة ذكيةreportstate
: يستدعي Home Graph API عند تغييرات حالة الجهاز.requestsync
: لتفعيل تحديثات أجهزة المستخدمين بدون الحاجة إلى إعادة ربط الحساب
الربط بمنصة Firebase
انتقِل إلى دليل washer-start
، ثم اضبط واجهة سطر الأوامر في Firebase باستخدام مشروع الإجراءات:
cd washer-start firebase use <project-id>
ضبط مشروع Firebase
يجب إعداد مشروع على Firebase.
firebase init
اختر ميزات CLI وقاعدة بيانات الوقت الفعلي والدوالّ وميزة الاستضافة التي تتضمّن "استضافة 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
سيؤدي ذلك إلى تهيئة واجهات برمجة التطبيقات والميزات اللازمة لمشروعك.
قم بتهيئة قاعدة بيانات الوقت الفعلي عندما يُطلب منك ذلك. يمكنك استخدام الموقع الافتراضي لمثيل قاعدة البيانات.
? 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
عند ضبط الدوال، يجب استخدام الملفات التلقائية والتأكّد من عدم استبدال ملفات 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
في حال إعادة إعداد المشروع، اختَر لا عند سؤالك ما إذا كنت تريد إعداد الدوال/.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 عن طريق الخطأ، تتوفر طريقتان لإيقافه:
- باستخدام واجهة المستخدم الرسومية، انتقِل إلى مجلد
../functions
ضمن المشروع، واختَر الملف المخفي.eslintrc.js
واحذفه. لا تخطئ في استخدام الاسم مثل.eslintrc.json
. - استخدام سطر الأوامر:
cd functions rm .eslintrc.js
النشر على Firebase
الآن بعد أن قمت بتثبيت التبعيات وإعداد مشروعك، فأنت جاهز لتشغيل التطبيق لأول مرة.
firebase deploy
هذه هي مخرجات وحدة التحكم التي يُفترض أن تظهر لك:
... ✔ Deploy complete! Project Console: https://console.firebase.google.com/project/<project-id>/overview Hosting URL: https://<project-id>.web.app
يؤدي هذا الأمر إلى نشر تطبيق ويب، مع العديد من دوال Cloud لمنصة Firebase.
افتح عنوان URL للاستضافة في متصفحك (https://<project-id>.web.app
) لعرض تطبيق الويب. ستظهر لك الواجهة التالية:
تمثّل واجهة مستخدم الويب هذه منصة تابعة لجهة خارجية من أجل عرض حالات الأجهزة أو تعديلها. لبدء ملء قاعدة البيانات بمعلومات الجهاز، انقر على تعديل. لن تظهر أي تغييرات في الصفحة، ولكن سيتم تخزين الحالة الحالية للغسّالة في قاعدة البيانات.
حان الوقت الآن لربط خدمة السحابة الإلكترونية التي نشرتها في "مساعد Google" باستخدام وحدة تحكّم الإجراءات.
ضبط مشروع وحدة تحكّم المهام
ضمن نظرة عامة > إنشاء الإجراء، اختَر إضافة إجراءات. أدخِل عنوان URL لوظيفة السحابة الإلكترونية التي توفّر تنفيذ أهداف المنزل المزوّد بأجهزة ذكية، وانقر على حفظ.
https://us-central1-<project-id>.cloudfunctions.net/smarthome
في علامة التبويب التطوير > الاستدعاء، أضِف الاسم المعروض للإجراء، ثم انقر على حفظ. سيظهر هذا الاسم في تطبيق Google Home.
لتفعيل ربط الحساب، انقر على الخيار تطوير > ربط الحساب في شريط التنقّل على يمين الصفحة. يمكنك استخدام إعدادات ربط الحساب التالية:
معرِّف العميل |
|
سر العميل |
|
عنوان URL للترخيص |
|
عنوان URL للرمز المميّز |
|
انقر على حفظ لحفظ إعدادات ربط الحساب، ثم انقر على اختبار لتفعيل الاختبار على مشروعك.
ستتم إعادة توجيهك إلى المحاكي. إذا لم تظهر لك عبارة "الاختبار مفعَّل الآن"، انقر على إعادة ضبط الاختبار للتأكّد من تفعيل الاختبار.
الربط بخدمة "مساعد Google"
من أجل اختبار الإجراء الخاص بمنزلك المزوّد بأجهزة ذكية، عليك ربط مشروعك بحساب على Google. ويتيح ذلك إجراء الاختبارات من خلال منصات "مساعد Google" وتطبيق Google Home الذين سجّلوا الدخول إلى الحساب نفسه.
- افتح إعدادات مساعد Google على هاتفك. ملاحظة: يجب تسجيل الدخول باستخدام الحساب نفسه الذي تستخدمه في وحدة التحكم.
- انتقِل إلى مساعد Google > الإعدادات > الإدارة الآلية للمنزل (ضمن "مساعد Google").
- انقر على رمز البحث في أعلى يسار الصفحة.
- ابحث عن تطبيقك التجريبي باستخدام البادئة [test] للعثور على تطبيقك التجريبي المحدّد.
- اختَر هذا العنصر. سيُجري "مساعد Google" بعد ذلك المصادقة مع خدمتك ويرسل طلب
SYNC
، ليطلب من الخدمة تقديم قائمة بالأجهزة للمستخدم.
يُرجى فتح تطبيق Google Home والتأكّد من رؤية جهاز الغسّالة.
تأكَّد من أنّه يمكنك التحكّم في الغسّالة باستخدام الطلبات الصوتية في تطبيق Google Home. من المفترض أيضًا أن تلاحظ تغيّر حالة الجهاز في واجهة مستخدم الويب الأمامية في واجهة المستخدم على السحابة الإلكترونية.
بما أنّه تم تشغيل غسّالة أساسية، يمكنك تخصيص الأوضاع المتوفّرة على جهازك.
4. إضافة أوضاع
تتيح السمة action.devices.traits.Modes
للجهاز إمكانية ضبط عدد عشوائي من الإعدادات للوضع، ويمكن ضبط إعداد واحد فقط في كل مرة. عليك إضافة وضع إلى الغسّالة لتحديد حجم ملابس الغسيل: صغيرة أو متوسطة أو كبيرة.
تعديل استجابة المزامنة
عليك إضافة معلومات عن السمة الجديدة إلى ردّك على "SYNC
" في "functions/index.js
". وتظهر هذه البيانات في مصفوفة traits
والعنصر attributes
كما هو موضَّح في مقتطف الرمز التالي.
index.js
app.onSync(body => {
return {
requestId: 'ff36a3cc-ec34-11e6-b1a0-64510650abcf',
payload: {
agentUserId: USER_ID,
devices: [{
id: 'washer',
type: 'action.devices.types.WASHER',
traits: [
'action.devices.traits.OnOff',
'action.devices.traits.StartStop',
'action.devices.traits.RunCycle',
// Add Modes trait
'action.devices.traits.Modes',
],
name: { ... },
deviceInfo: { ... },
attributes: {
pausable: true,
//Add availableModes
availableModes: [{
name: 'load',
name_values: [{
name_synonym: ['load'],
lang: 'en',
}],
settings: [{
setting_name: 'small',
setting_values: [{
setting_synonym: ['small'],
lang: 'en',
}]
}, {
setting_name: 'medium',
setting_values: [{
setting_synonym: ['medium'],
lang: 'en',
}]
}, {
setting_name: 'large',
setting_values: [{
setting_synonym: ['large'],
lang: 'en',
}]
}],
ordered: true,
}],
},
}],
},
};
});
إضافة أوامر "تنفيذ الهدف" الجديدة
في غرض EXECUTE
، أضِف الأمر action.devices.commands.SetModes
كما هو موضّح في مقتطف الرمز التالي.
index.js
const updateDevice = async (execution,deviceId) => {
const {params,command} = execution;
let state, ref;
switch (command) {
case 'action.devices.commands.OnOff':
state = {on: params.on};
ref = firebaseRef.child(deviceId).child('OnOff');
break;
case 'action.devices.commands.StartStop':
state = {isRunning: params.start};
ref = firebaseRef.child(deviceId).child('StartStop');
break;
case 'action.devices.commands.PauseUnpause':
state = {isPaused: params.pause};
ref = firebaseRef.child(deviceId).child('StartStop');
Break;
// Add SetModes command
case 'action.devices.commands.SetModes':
state = {load: params.updateModeSettings.load};
ref = firebaseRef.child(deviceId).child('Modes');
break;
}
تعديل ردّ QUERY
يُرجى بعد ذلك تعديل ردّ "QUERY
" للإبلاغ عن حالة الغسّالة الحالية.
أضف التغييرات المحدثة إلى الدالتين queryFirebase
وqueryDevice
للحصول على الحالة كما تم تخزينها في قاعدة بيانات الوقت الفعلي.
index.js
const queryFirebase = async (deviceId) => {
const snapshot = await firebaseRef.child(deviceId).once('value');
const snapshotVal = snapshot.val();
return {
on: snapshotVal.OnOff.on,
isPaused: snapshotVal.StartStop.isPaused,
isRunning: snapshotVal.StartStop.isRunning,
// Add Modes snapshot
load: snapshotVal.Modes.load,
};
}
const queryDevice = async (deviceId) => {
const data = await queryFirebase(deviceId);
return {
on: data.on,
isPaused: data.isPaused,
isRunning: data.isRunning,
currentRunCycle: [{ ... }],
currentTotalRemainingTime: 1212,
currentCycleRemainingTime: 301,
// Add currentModeSettings
currentModeSettings: {
load: data.load,
},
};
};
تعديل حالة التقرير
وأخيرًا، عليك تعديل وظيفة "reportstate
" لضبط إعدادات الحمولة الحالية في الغسّالة على قاعدة البيانات Home Graph.
index.js
const requestBody = {
requestId: 'ff36a3cc', /* Any unique ID */
agentUserId: USER_ID,
payload: {
devices: {
states: {
/* Report the current state of your washer */
[context.params.deviceId]: {
on: snapshot.OnOff.on,
isPaused: snapshot.StartStop.isPaused,
isRunning: snapshot.StartStop.isRunning,
// Add currentModeSettings
currentModeSettings: {
load: snapshot.Modes.load,
},
},
},
},
},
};
النشر على Firebase
شغِّل الأمر التالي لنشر الإجراء المعدّل:
firebase deploy --only functions
بعد اكتمال النشر، انتقِل إلى واجهة مستخدم الويب وانقر على زر إعادة تحميل في شريط الأدوات. يؤدّي ذلك إلى تفعيل ميزة "طلب المزامنة" لكي يتلقّى "مساعد Google" بيانات استجابة SYNC
المعدَّلة.
يمكنك الآن توجيه أمر لضبط وضع الغسّالة، مثلاً:
"Ok Google، أريد ضبط مستوى تحميل الغسّالة على كبير"
بالإضافة إلى ذلك، يمكنك طرح أسئلة حول الغسّالة، مثلاً:
"Ok Google، ما هو مستوى تحميل الغسّالة؟"
5- إضافة مفاتيح تبديل
تمثل السمة action.devices.traits.Toggles
الجوانب المُسمّاة للجهاز الذي تم ضبط حالته على "صحيح" أو "خطأ"، مثلاً ما إذا كانت الغسّالة في الوضع "توربو" أم لا.
تعديل استجابة المزامنة
في ردّ SYNC
، عليك إضافة معلومات حول سمة الجهاز الجديدة. سيظهر في مصفوفة traits
والكائن attributes
كما هو موضّح في مقتطف الرمز التالي.
index.js
app.onSync(body => {
return {
requestId: 'ff36a3cc-ec34-11e6-b1a0-64510650abcf',
payload: {
agentUserId: USER_ID,
devices: [{
id: 'washer',
type: 'action.devices.types.WASHER',
traits: [
'action.devices.traits.OnOff',
'action.devices.traits.StartStop',
'action.devices.traits.RunCycle',
'action.devices.traits.Modes',
// Add Toggles trait
'action.devices.traits.Toggles',
],
name: { ... },
deviceInfo: { ... },
attributes: {
pausable: true,
availableModes: [{
name: 'load',
name_values: [{
name_synonym: ['load'],
lang: 'en'
}],
settings: [{ ... }],
ordered: true,
}],
//Add availableToggles
availableToggles: [{
name: 'Turbo',
name_values: [{
name_synonym: ['turbo'],
lang: 'en',
}],
}],
},
}],
},
};
});
إضافة أوامر "تنفيذ الغرض" الجديدة
في غرض EXECUTE
، أضِف الأمر action.devices.commands.SetToggles
كما هو موضّح في مقتطف الرمز التالي.
index.js
const updateDevice = async (execution,deviceId) => {
const {params,command} = execution;
let state, ref;
switch (command) {
case 'action.devices.commands.OnOff':
state = {on: params.on};
ref = firebaseRef.child(deviceId).child('OnOff');
break;
case 'action.devices.commands.StartStop':
state = {isRunning: params.start};
ref = firebaseRef.child(deviceId).child('StartStop');
break;
case 'action.devices.commands.PauseUnpause':
state = {isPaused: params.pause};
ref = firebaseRef.child(deviceId).child('StartStop');
break;
case 'action.devices.commands.SetModes':
state = {load: params.updateModeSettings.load};
ref = firebaseRef.child(deviceId).child('Modes');
break;
// Add SetToggles command
case 'action.devices.commands.SetToggles':
state = {Turbo: params.updateToggleSettings.Turbo};
ref = firebaseRef.child(deviceId).child('Toggles');
break;
}
تعديل ردّ QUERY
أخيرًا، يجب تعديل استجابة "QUERY
" للإبلاغ عن الوضع "توربو" في الغسّالة. أضف التغييرات المحدثة إلى الدالتين queryFirebase
وqueryDevice
للحصول على حالة التبديل كما هي مخزنة في قاعدة بيانات الوقت الفعلي.
index.js
const queryFirebase = async (deviceId) => {
const snapshot = await firebaseRef.child(deviceId).once('value');
const snapshotVal = snapshot.val();
return {
on: snapshotVal.OnOff.on,
isPaused: snapshotVal.StartStop.isPaused,
isRunning: snapshotVal.StartStop.isRunning,
load: snapshotVal.Modes.load,
// Add Toggles snapshot
Turbo: snapshotVal.Toggles.Turbo,
};
}
const queryDevice = async (deviceId) => {
const data = queryFirebase(deviceId);
return {
on: data.on,
isPaused: data.isPaused,
isRunning: data.isRunning,
currentRunCycle: [{ ... }],
currentTotalRemainingTime: 1212,
currentCycleRemainingTime: 301,
currentModeSettings: {
load: data.load,
},
// Add currentToggleSettings
currentToggleSettings: {
Turbo: data.Turbo,
},
};
};
تعديل حالة التقرير
وأخيرًا، يُرجى تعديل وظيفة "reportstate
" لإرسال تقرير إلى قاعدة البيانات Home Graph عما إذا كانت الغسّالة مضبوطة على الوضع "توربو".
index.js
const requestBody = {
requestId: 'ff36a3cc', /* Any unique ID */
agentUserId: USER_ID,
payload: {
devices: {
states: {
/* Report the current state of your washer */
[context.params.deviceId]: {
on: snapshot.OnOff.on,
isPaused: snapshot.StartStop.isPaused,
isRunning: snapshot.StartStop.isRunning,
currentModeSettings: {
load: snapshot.Modes.load,
},
// Add currentToggleSettings
currentToggleSettings: {
Turbo: snapshot.Toggles.Turbo,
},
},
},
},
},
};
النشر على Firebase
شغِّل الأمر التالي لنشر الدوال المُعدَّلة:
firebase deploy --only functions
انقر على زر إعادة التحميل في واجهة مستخدم الويب لتفعيل "طلب المزامنة" بعد اكتمال النشر.
يمكنك الآن توجيه طلب لضبط الغسّالة على الوضع "توربو" من خلال قول:
"Ok Google، أريد تفعيل ميزة التهوية في الغسّالة"
يمكنك أيضًا معرفة ما إذا كانت الغسّالة في الوضع "توربو" من خلال طرح السؤال التالي:
"Ok Google، هل الغسّالة في وضع Turbo؟"
6. الإبلاغ عن الأخطاء والاستثناءات
تتيح لك معالجة الأخطاء في إجراء المنزل المزوّد بأجهزة ذكية إبلاغ المستخدمين عندما تؤدي المشاكل إلى تعذُّر الاستجابات من خلال EXECUTE
وQUERY
. تؤدي الإشعارات إلى توفير تجربة مستخدم أكثر إيجابية لدى المستخدمين عند تفاعلهم مع جهازك الذكي و"الإجراء".
في أي وقت يتعذّر فيه إرسال طلب EXECUTE
أو QUERY
، من المفترض أن يعرض الإجراء الخاص بك رمز خطأ. على سبيل المثال، إذا أردت عرض خطأ عندما يحاول المستخدم تشغيل الغسّالة مع فتح غطاءها، ستبدو استجابة EXECUTE
على النحو التالي: مقتطف الرمز التالي:
{
"requestId": "ff36a3cc-ec34-11e6-b1a0-64510650abcf",
"payload": {
"commands": [
{
"ids": [
"456"
],
"status": "ERROR",
"errorCode": "deviceLidOpen"
}
]
}
}
عندما يطلب أحد المستخدمين تشغيل الغسّالة، يردّ "مساعد Google" قائلاً:
"غطاء الغسّالة مفتوح. يُرجى إغلاقه وإعادة المحاولة".
تتشابه الاستثناءات مع الأخطاء، ولكنها تشير إلى الحالات التي يكون فيها تنبيه مرتبطًا بأمر، والذي قد يؤدي إلى حظر التنفيذ الناجح أو لا. يمكن أن يقدِّم أحد الاستثناءات معلومات ذات صلة باستخدام السمة StatusReport
، مثل مستوى البطارية أو التغيير الأخير في الحالة. يتم عرض رموز الاستثناء التي لا تحظر الحظر مع حالة SUCCESS
، بينما يتم عرض رموز استثناء الحظر بالحالة EXCEPTIONS
.
يوجد مثال على استجابة مع استثناء في مقتطف الرمز التالي:
{
"requestId": "ff36a3cc-ec34-11e6-b1a0-64510650abcf",
"payload": {
"commands": [{
"ids": ["123"],
"status": "SUCCESS",
"states": {
"online": true,
"isPaused": false,
"isRunning": false,
"exceptionCode": "runCycleFinished"
}
}]
}
}
يستجيب "مساعد Google" بقول:
"انتهت عمل الغسّالة".
لإضافة تقارير الأخطاء في الغسّالة، افتح functions/index.js
وأضِف تعريف فئة الخطأ كما هو موضّح في مقتطف الرمز التالي:
index.js
app.onQuery(async (body) => {...});
// Add SmartHome error handling
class SmartHomeError extends Error {
constructor(errorCode, message) {
super(message);
this.name = this.constructor.name;
this.errorCode = errorCode;
}
}
عدِّل استجابة التنفيذ لعرض رمز الخطأ وحالة الخطأ:
index.js
const executePromises = [];
const intent = body.inputs[0];
for (const command of intent.payload.commands) {
for (const device of command.devices) {
for (const execution of command.execution) {
executePromises.push( ... )
//Add error response handling
.catch((error) => {
functions.logger.error('EXECUTE', device.id, error);
result.ids.push(device.id);
if(error instanceof SmartHomeError) {
result.status = 'ERROR';
result.errorCode = error.errorCode;
}
})
);
}
}
}
بإمكان "مساعد Google" الآن إخبار المستخدمين بأي رمز خطأ تُبلغ عنه. سترى مثالاً محددًا في القسم التالي.
7. إضافة عملية ثانوية لإثبات هوية المستخدم
يجب تنفيذ عملية التحقق الثانوي من المستخدم في الإجراء الخاص بك إذا كان جهازك يتضمن أي أوضاع يجب تأمينها أو يجب أن تقتصر على مجموعة معيّنة من المستخدمين المصرّح لهم، مثل تحديث البرامج أو إلغاء الربط.
يمكنك تنفيذ التحقُّق الثانوي من المستخدِم على جميع أنواع الأجهزة وسماتها، وتخصيص ما إذا كان تحدُّ الأمان يحدث في كل مرة أو يلزم استيفاء معايير معيَّنة.
هناك ثلاثة أنواع من الاختبارات المتاحة:
No
challenge
: طلب واستجابة لا يستخدمان اختبار مصادقة (هذا هو السلوك التلقائي)ackNeeded
: عملية تحقُّق ثانوية للمستخدم وتتطلب إقرارًا صريحًا (نعم أو لا)pinNeeded
: عملية تحقّق ثانوية للمستخدم وتتطلب رقم التعريف الشخصي (PIN)
بالنسبة إلى هذا الدرس التطبيقي حول الترميز، أضِف اختبار التحقق ackNeeded
إلى الأمر الخاص بتشغيل الغسّالة والوظيفة التي تؤدي إلى عرض خطأ في حال تعذّر إجراء اختبار التحقّق الثانوي.
افتح functions/index.js
، وأضِف تعريف فئة الخطأ الذي يعرض رمز الخطأ ونوع الاختبار كما هو موضّح في مقتطف الرمز التالي:
index.js
class SmartHomeError extends Error { ... }
// Add secondary user verification error handling
class ChallengeNeededError extends SmartHomeError {
/**
* Create a new ChallengeNeededError
* @param {string} suvType secondary user verification challenge type
*/
constructor(suvType) {
super('challengeNeeded', suvType);
this.suvType = suvType;
}
}
تحتاج أيضًا إلى تعديل استجابة التنفيذ لعرض خطأ challengeNeeded
على النحو التالي:
index.js
const executePromises = [];
const intent = body.inputs[0];
for (const command of intent.payload.commands) {
for (const device of command.devices) {
for (const execution of command.execution) {
executePromises.push( ... )
.catch((error) => {
functions.logger.error('EXECUTE', device.id, error);
result.ids.push(device.id);
if(error instanceof SmartHomeError) {
result.status = 'ERROR';
result.errorCode = error.errorCode;
//Add error response handling
if(error instanceof ChallengeNeededError) {
result.challengeNeeded = {
type: error.suvType
};
}
}
})
);
}
}
}
وأخيرًا، يُرجى تعديل "updateDevice
" لطلب الموافقة الصريحة على تشغيل الغسّالة أو إيقافها.
index.js
const updateDevice = async (execution,deviceId) => {
const {challenge,params,command} = execution; //Add secondary user challenge
let state, ref;
switch (command) {
case 'action.devices.commands.OnOff':
//Add secondary user verification challenge
if (!challenge || !challenge.ack) {
throw new ChallengeNeededError('ackNeeded');
}
state = {on: params.on};
ref = firebaseRef.child(deviceId).child('OnOff');
break;
...
}
return ref.update(state)
.then(() => state);
};
النشر على Firebase
شغِّل الأمر التالي لنشر الدالة المعدّلة:
firebase deploy --only functions
بعد تفعيل الرمز المعدَّل، يجب الإقرار شفهيًا بالإجراءات التي تنفّذها عندما تطلب من "مساعد Google" تشغيل الغسّالة أو إيقافها على النحو التالي:
أنت: "Ok Google، أريد تشغيل الغسّالة".
المساعد: "هل المطلوب فعلاً تشغيل الغسّالة؟"
أنت: "نعم"
يمكنك أيضًا الاطّلاع على ردّ تفصيلي لكل خطوة من خطوات عملية التحقّق الثانوي من المستخدِم من خلال فتح سجلّات Firebase.
8. تهانينا
تهانينا لقد وسّعت نطاق ميزات إجراءات المنزل المزوّد بأجهزة ذكية من خلال السمتَين Modes
وToggles
، وأمّن تنفيذها من خلال عملية تحقُّق ثانوية من المستخدم.
مزيد من المعلومات
في ما يلي بعض الأفكار التي يمكنك تنفيذها للتعمق أكثر:
- إضافة إمكانات التنفيذ المحلي إلى أجهزتك
- لتعديل حالة جهازك، استخدِم نوعًا مختلفًا من تحدّي التحقق من المستخدم الثانوي.
- يمكنك تعديل استجابة QUERY للسمة
RunCycle
ليتم تحديثها ديناميكيًا. - يمكنك الاطّلاع على نموذج GitHub.