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.
- انقر على إنشاء مشروع، وأدخِل اسمًا للمشروع، ثم انقر على إنشاء مشروع.
اختيار الدمج من السحابة الإلكترونية إلى السحابة الإلكترونية
في صفحة المشروع الرئيسية في "وحدة تحكّم المطوّر"، اختَر إضافة عملية دمج من السحابة الإلكترونية إلى السحابة الإلكترونية ضمن من السحابة الإلكترونية إلى السحابة الإلكترونية.
تثبيت Firebase CLI
ستسمح لك واجهة سطر أوامر Firebase (CLI) بعرض تطبيقات الويب محليًا ونشر تطبيق الويب في استضافة Firebase.
لتثبيت واجهة برمجة التطبيقات، شغِّل الأمر npm التالي من الوحدة الطرفية:
npm install -g firebase-tools
للتحقّق من تثبيت واجهة برمجة التطبيقات بشكل صحيح، يمكنك تنفيذ ما يلي:
firebase --version
فوِّض واجهة Firebase CLI باستخدام حسابك على Google من خلال تنفيذ:
firebase login
إنشاء مشروع على Firebase
- انتقِل إلى Firebase.
- انقر على إنشاء مشروع وأدخِل اسم مشروعك.
- ضَع علامة في مربّع الاختيار الخاص بالاتفاقية وانقر على متابعة. إذا لم يكن هناك مربّع اختيار للاتفاقية، يمكنك تخطّي هذه الخطوة.
- بعد إنشاء مشروعك على Firebase، ابحث عن رقم تعريف المشروع. انتقِل إلى نظرة عامة على المشروع وانقر على رمز الإعدادات > إعدادات المشروع.
- يظهر مشروعك ضمن علامة التبويب عام.
تفعيل 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 <firebase-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 عن طريق الخطأ، تتوفّر طريقتان لإيقافه:
- باستخدام واجهة المستخدم الرسومية، انتقِل إلى مجلد
../functions
ضمن المشروع، واختَر الملف المخفي.eslintrc.js
واحذِفه. لا تخلط بينه وبين.eslintrc.json
الذي يحمل اسمًا مشابهًا. - باستخدام سطر الأوامر:
cd functions rm .eslintrc.js
النشر على Firebase
بعد تثبيت التبعيات وضبط مشروعك، أصبحت جاهزًا لتشغيل التطبيق للمرّة الأولى.
firebase deploy
في ما يلي نتائج وحدة التحكّم التي من المفترض أن تظهر لك:
... ✔ Deploy complete! Project Console: https://console.firebase.google.com/project/<firebase-project-id>/overview Hosting URL: https://<firebase-project-id>.web.app
ينشر هذا الأمر تطبيق ويب، بالإضافة إلى العديد من وظائف السحابة الإلكترونية لبرنامج Firebase.
افتح عنوان URL للاستضافة في المتصفّح (https://<firebase-project-id>.web.app
) لعرض تطبيق الويب. ستظهر لك الواجهة التالية:
تمثّل واجهة مستخدم الويب هذه منصة تابعة لجهة خارجية لعرض حالات الجهاز أو تعديلها. لبدء تعبئة قاعدة بياناتك بمعلومات الأجهزة، انقر على تعديل. لن تلاحظ أي تغييرات على الصفحة، ولكن سيتم تخزين الحالة الحالية للغسالة في قاعدة البيانات.
حان الآن وقت ربط خدمة السحابة الإلكترونية التي تم نشرها بخدمة "مساعد Google" باستخدام وحدة تحكّم المطوّر.
ضبط مشروعك على Developer Console
في علامة التبويب تطوير، أضِف اسمًا معروضًا للتفاعل. سيظهر هذا الاسم في تطبيق Google Home.
ضمن علامة التطبيق التجارية، حمِّل ملف png
لرمز التطبيق بحجم 144 × 144 بكسل واسمه
.
لتفعيل ميزة ربط الحساب، استخدِم إعدادات ربط الحساب التالية:
معرِّف العميل |
|
سر العميل |
|
عنوان URL للترخيص |
|
عنوان URL للرمز المميّز |
|
ضمن عنوان URL لتنفيذ الإجراءات في السحابة الإلكترونية، أدخِل عنوان URL لوظيفة السحابة الإلكترونية التي توفّر إجراءات تنفيذ طلبات المنزل الذكي.
https://us-central1-
انقر على حفظ لحفظ إعدادات مشروعك، ثمّ انقر على التالي: اختبار لتفعيل الاختبار في مشروعك.
يمكنك الآن البدء في تنفيذ وحدات ربط الويب اللازمة لربط حالة الجهاز بخدمة "مساعد Google".
الربط بخدمة "مساعد Google"
لاختبار عملية الدمج من السحابة الإلكترونية إلى السحابة الإلكترونية، عليك ربط مشروعك بحساب Google. يتيح ذلك إجراء الاختبار من خلال مساحات عرض "مساعد Google" وتطبيق Google Home اللذَين تم تسجيل الدخول إلى الحساب نفسه من خلالهما.
- على هاتفك، افتح إعدادات "مساعد Google". يُرجى العلم أنّه يجب تسجيل الدخول باستخدام الحساب نفسه المستخدَم في وحدة التحكّم.
- انتقِل إلى مساعد Google > الإعدادات > التحكّم في المنزل (ضمن "مساعد Google").
- انقر على رمز البحث في أعلى يسار الصفحة.
- ابحث عن تطبيقك التجريبي باستخدام البادئة [test] للعثور على تطبيقك التجريبي المحدّد.
- اختَر هذا العنصر. سيصلك بعد ذلك طلب من "مساعد Google" لإثبات هويتك من خلال خدمتك، وسيطلب من خدمتك تقديم قائمة بالأجهزة للمستخدم.
SYNC
افتح تطبيق Google Home وتأكَّد من ظهور غسّالة الملابس.
تأكَّد من أنّه يمكنك التحكّم في الغسالة باستخدام الطلبات الصوتية في تطبيق Google Home. من المفترض أيضًا أن تلاحظ تغيير حالة الجهاز في واجهة مستخدم الويب الأمامية لخدمة السحابة الإلكترونية.
بعد نشر غسّالة أساسية، يمكنك تخصيص الأوضاع المتاحة على جهازك.
4. إضافة أوضاع
تتيح السمة action.devices.traits.Modes
للجهاز الحصول على عدد عشوائي من الإعدادات لأحد الأوضاع، ولا يمكن ضبط سوى إعداد واحد في كل مرة. ستضيف وضعًا إلى الغسالة لتحديد حجم حمولة الغسيل: صغير أو متوسط أو كبير.
تعديل استجابة SYNC
عليك إضافة معلومات عن السمة الجديدة إلى ردّك على 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
للإبلاغ عن إعداد الحمولة الحالي للغسالة في "الرسم البياني للمنزل".
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
جوانب مُسمّاة للجهاز لها حالة صحيحة أو خطأ، مثل ما إذا كانت الغسالة في وضع Turbo.
تعديل استجابة SYNC
في ردّك على 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
للإبلاغ إلى "رسم بياني للمنزل" عمّا إذا تم ضبط الغسالة على وضع "التربو".
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، أريد تفعيل وضع Turbo في الغسالة".
يمكنك أيضًا التحقّق ممّا إذا كانت الغسّالة في وضع "التوربو" من خلال طرح الأسئلة التالية:
"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(
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
QUERY للسمة من أجل التعديل بشكل ديناميكي. - اطّلِع على نموذج GitHub هذا.