1. قبل البدء
تستخدم عمليات الدمج بين الخدمات السحابية أنواع الأجهزة لإعلام "مساعد Google" بالقواعد اللغوية التي يجب استخدامها مع جهاز معيّن. تحدّد سمات الجهاز إمكانات نوع الجهاز. يرث الجهاز حالات كل سمة جهاز تمت إضافتها إلى عملية الدمج.
يمكنك ربط أي سمات متوافقة بنوع الجهاز الذي اخترته لتخصيص وظائف أجهزة المستخدمين. إذا أردت تنفيذ سمات مخصّصة في "الإجراءات" غير متاحة حاليًا في مخطط الجهاز، تتيح لك سمتا الأوضاع ومفاتيح التبديل التحكّم في إعدادات معيّنة باستخدام اسم مخصّص تحدّده أنت.
بالإضافة إلى إمكانية التحكّم الأساسية التي توفّرها الأنواع والسمات، تتضمّن Smart Home API ميزات إضافية لتحسين تجربة المستخدم. تقدّم ردود الأخطاء ملاحظات تفصيلية للمستخدم عندما لا تنجح الطلبات. توسّع ميزة "التحقّق من المستخدم الثانوي" نطاق هذه الردود وتضيف أمانًا إضافيًا إلى سمة الجهاز التي تختارها. من خلال إرسال ردود أخطاء معيّنة إلى حظر التحدّي الصادر من "مساعد Google"، يمكن أن تتطلّب عملية الربط بين الخدمات السحابية الحصول على تفويض إضافي لإكمال أمر معيّن.
المتطلبات الأساسية
- دليل المطوّرين حول إنشاء عملية دمج من السحابة الإلكترونية إلى السحابة الإلكترونية
- درس تطبيقي حول الترميز في "الغسالة الذكية"
- أنواع الأجهزة وسماتها دليل المطوّرين
ما ستنشئه
في هذا الدرس العملي، ستنفّذ عملية دمج مسبقة الإنشاء مع Firebase، ثم ستتعرّف على كيفية إضافة سمات غير عادية إلى الغسّالة الذكية لتحديد حجم الحمولة ووضع التشغيل السريع. ستنفّذ أيضًا عملية إعداد التقارير عن الأخطاء والاستثناءات، وتتعرّف على كيفية فرض إقرار شفهي لتشغيل الغسالة باستخدام عملية التحقّق الثانوية من هوية المستخدم.
المُعطيات
- كيفية إضافة سمات "الأوضاع" و"أزرار التبديل" إلى عملية الدمج
- كيفية الإبلاغ عن الأخطاء والاستثناءات
- كيفية تطبيق إجراء ثانوي لإثبات هوية المستخدم
المتطلبات
- متصفّح ويب، مثل Google Chrome
- جهاز iOS أو Android مثبَّت عليه تطبيق Google Home
- الإصدار 10.16 من Node.js أو إصدار أحدث
- حساب Google
- حساب فوترة على Google Cloud
2. الخطوات الأولى
تفعيل "عناصر التحكّم في النشاط"
لاستخدام "مساعد Google"، عليك مشاركة بيانات نشاط معيّنة مع Google. يحتاج "مساعد Google" إلى هذه البيانات ليعمل بشكلٍ سليم، ولكنّ شرط مشاركة البيانات ليس خاصًا بحزمة تطوير البرامج (SDK). لمشاركة هذه البيانات، عليك إنشاء حساب على Google إذا لم يكن لديك حساب. يمكنك استخدام أي حساب على Google، وليس بالضرورة أن يكون حساب المطوِّر.
افتح صفحة "عناصر التحكّم في النشاط" لحساب Google الذي تريد استخدامه مع "مساعد Google".
تأكَّد من تفعيل مفاتيح التبديل التالية:
- النشاط على الويب وفي التطبيقات: بالإضافة إلى ذلك، احرص على وضع علامة في المربّع تضمين سجلّ Chrome والأنشطة من المواقع الإلكترونية والتطبيقات والأجهزة التي تستخدم خدمات Google.
- معلومات الجهاز
- التفاعل الصوتي مع الجهاز
إنشاء مشروع دمج من السحابة الإلكترونية إلى السحابة الإلكترونية
- انتقِل إلى Play Console.
- انقر على إنشاء مشروع، وأدخِل اسمًا للمشروع، ثم انقر على إنشاء مشروع.
اختيار عملية الدمج من السحابة الإلكترونية إلى السحابة الإلكترونية
في الصفحة الرئيسية للمشروع في Developer Console، انقر على إضافة عملية دمج من السحابة الإلكترونية إلى السحابة الإلكترونية ضمن من السحابة الإلكترونية إلى السحابة الإلكترونية.
تثبيت Firebase CLI
ستتيح لك واجهة سطر الأوامر (CLI) في Firebase عرض تطبيقات الويب محليًا ونشر تطبيق الويب على خدمة استضافة Firebase.
لتثبيت واجهة سطر الأوامر، شغِّل أمر npm التالي من الوحدة الطرفية:
npm install -g firebase-tools
للتحقّق من تثبيت واجهة سطر الأوامر بشكل صحيح، نفِّذ ما يلي:
firebase --version
امنح إذنًا لواجهة سطر الأوامر (CLI) في Firebase باستخدام حسابك على Google من خلال تنفيذ ما يلي:
firebase login
إضافة Firebase إلى مشروعك في Google Home Developer Console
الطريقة 1: من خلال وحدة تحكّم Firebase
- انتقِل إلى Firebase.
- انقر على إنشاء مشروع على Firebase.
- في شاشة إنشاء مشروع، انقر على إضافة Firebase إلى مشروع Google Cloud.
- في شاشة البدء، اختَر مشروع Google Cloud الذي أنشأته للتو في Google Home Developer Console، ثم انقر على متابعة.
الطريقة 2: من خلال Firebase CLI
firebase projects:addfirebase
اختَر مشروع Google Home Developer Console الذي أنشأته للتو لإضافة Firebase.
عند إضافة Firebase إلى مشروعك على Google Home Developer Console، سيظهر في Firebase Console. سيتوافق رقم تعريف مشروع Firebase مع رقم تعريف مشروعك على Google Home Developer Console.
تفعيل HomeGraph API
تتيح HomeGraph API تخزين الأجهزة وحالاتها والاستعلام عنها ضمن قاعدة بيانات Home Graph الخاصة بالمستخدم. لاستخدام واجهة برمجة التطبيقات هذه، عليك أولاً فتح وحدة تحكّم Google Cloud وتفعيل HomeGraph API.
في Google Cloud Console، احرص على اختيار المشروع الذي يتطابق مع "الإجراءات" <firebase-project-id>.
ثم انقر على تفعيل في شاشة "مكتبة واجهات برمجة التطبيقات" الخاصة بواجهة HomeGraph API.
3- تشغيل التطبيق النموذجي
بعد إعداد بيئة التطوير، يمكنك نشر المشروع التجريبي للتأكّد من ضبط كل شيء بشكلٍ صحيح.
الحصول على رمز المصدر
انقر على الرابط التالي لتنزيل نموذج هذا الدرس العملي على جهاز التطوير:
...أو يمكنك استنساخ مستودع GitHub من سطر الأوامر:
git clone https://github.com/google-home/smarthome-traits.git
فكّ ضغط ملف ZIP الذي تم تنزيله.
لمحة عن المشروع
يحتوي المشروع الأوّلي على الدلائل الفرعية التالية:
public:
واجهة مستخدم أمامية للتحكّم في حالة الغسالة الذكية ومراقبتها بسهولةfunctions:
خدمة سحابية تم تنفيذها بالكامل وتدير الغسالة الذكية باستخدام "وظائف السحابة الإلكترونية في Firebase" و"قاعدة بيانات Firebase الآنية الاستجابة".
يتضمّن التنفيذ السحابي المقدَّم الوظائف التالية في index.js
:
-
fakeauth
: نقطة نهاية التفويض لربط الحسابات -
faketoken
: نقطة نهاية الرمز المميّز لربط الحسابات -
smarthome
: نقطة نهاية تنفيذ طلبات المنزل الذكي -
reportstate
: يستدعي Home Graph API عند حدوث تغييرات في حالة الجهاز requestsync
: تتيح للمستخدمين تحديث أجهزتهم بدون الحاجة إلى إعادة ربط الحساب
الربط مع Firebase
انتقِل إلى الدليل washer-start
، ثمّ أعدّ واجهة سطر الأوامر Firebase CLI باستخدام مشروع الدمج:
cd washer-start firebase use <project-id>
إعداد مشروع Firebase
إعداد مشروع Firebase
firebase init
اختَر ميزات واجهة سطر الأوامر وRealtime Database وميزة Functions.
? Which Firebase features do you want to set up for this directory? Press Space to select features, then Enter to confirm your choices. (Press <space> to select, <a> to toggle all, <i> to invert selection, and <enter> to proceed) >( ) Data Connect: Set up a Firebase Data Connect service ( ) Firestore: Configure security rules and indexes files for Firestore ( ) Genkit: Setup a new Genkit project with Firebase (*) Functions: Configure a Cloud Functions directory and its files ( ) App Hosting: Configure an apphosting.yaml file for App Hosting ( ) Hosting: Configure files for Firebase Hosting and (optionally) 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: Configure a security rules file for Realtime Database and (optionally) provision default instance ( ) Data Connect: Set up a Firebase Data Connect service ( ) Firestore: Configure security rules and indexes files for Firestore
سيؤدي ذلك إلى تهيئة واجهات برمجة التطبيقات والميزات اللازمة لمشروعك.
عندما يُطلب منك ذلك، ابدأ 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
عند ضبط إعدادات "الدوال"، عليك استخدام الملفات التلقائية والتأكّد من عدم الكتابة فوق ملفَي 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
إذا تم تفعيل 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
ينشر هذا الأمر تطبيقًا على الويب، بالإضافة إلى العديد من وظائف Firebase السحابية.
افتح عنوان URL للاستضافة في المتصفّح (https://<firebase-project-id>.web.app
) لعرض تطبيق الويب. ستظهر لك الواجهة التالية:
تمثّل واجهة مستخدم الويب هذه منصة تابعة لجهة خارجية لعرض حالات الأجهزة أو تعديلها. لبدء ملء قاعدة البيانات بمعلومات الجهاز، انقر على تعديل. لن تظهر أي تغييرات على الصفحة، ولكن سيتم تخزين الحالة الحالية للغسالة في قاعدة البيانات.
حان الوقت الآن لربط الخدمة السحابية التي نشرتها بخدمة "مساعد Google" باستخدام Developer Console.
ضبط مشروعك في Developer Console
في علامة التبويب تطوير، أضِف اسمًا معروضًا للتفاعل. سيظهر هذا الاسم في تطبيق Google Home.
ضِمن العلامة التجارية للتطبيق، حمِّل ملف png
لرمز التطبيق بحجم 144 × 144 بكسل، وأطلِق عليه الاسم
.
لتفعيل ربط الحساب، استخدِم إعدادات ربط الحساب التالية:
معرِّف العميل |
|
سر العميل |
|
عنوان URL للترخيص |
|
عنوان URL للرمز المميز |
|
ضمن عنوان URL لتنفيذ الطلبات على السحابة الإلكترونية، أدخِل عنوان URL لوظيفة السحابة الإلكترونية التي توفّر تنفيذ الطلبات المتعلقة بأجهزة المنزل الذكي.
https://us-central1-<project-id>.cloudfunctions.net/smarthome
انقر على حفظ لحفظ إعدادات مشروعك، ثمّ انقر على التالي: اختبار لتفعيل الاختبار في مشروعك.
يمكنك الآن البدء في تنفيذ خطافات الويب اللازمة لربط حالة الجهاز بالمساعد.
الربط بـ "مساعد 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
في EXECUTE
intent، أضِف الأمر 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
للحصول على الحالة كما هي مخزَّنة في Realtime Database.
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
في EXECUTE
intent، أضِف الأمر 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
للحصول على حالة زر التبديل كما هو مخزَّن في Realtime Database.
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، أريد ضبط الغسالة على وضع السرعة الفائقة ("Hey Google, set the washer to turbo mode").
يمكنك أيضًا التحقّق ممّا إذا كانت الغسالة في وضع Turbo من خلال طرح السؤال التالي:
"Ok Google، هل الغسالة في وضع التشغيل السريع؟"
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(
updateDevice(execution, device.id)
.then((data) => {
...
})
//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(
updateDevice(execution, device.id)
.then((data) => {
...
})
.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، أريد تشغيل الغسّالة".
مساعد Google: "هل تريد فعلاً تشغيل الغسالة؟"
أنت: "نعم".
يمكنك أيضًا الاطّلاع على ردّ تفصيلي لكل خطوة من خطوات عملية إثبات هوية المستخدم الثانوي من خلال فتح سجلات Firebase.
8. تهانينا
تهانينا! لقد وسّعت ميزات عمليات الدمج من السحابة الإلكترونية إلى السحابة الإلكترونية من خلال السمتَين Modes
وToggles
، وأمّنت تنفيذها من خلال عملية التحقّق الثانوية من هوية المستخدم.
مزيد من المعلومات
في ما يلي بعض الأفكار التي يمكنك تنفيذها للتعمّق أكثر:
- أضِف إمكانات التنفيذ المحلي إلى أجهزتك.
- استخدِم نوعًا مختلفًا من تحدّي التحقّق الثانوي من المستخدِم لتعديل حالة جهازك.
- عدِّل ردّ
RunCycle
طلب البحث عن السمة ليتم تعديله ديناميكيًا. - استكشِف نموذج GitHub هذا.