لتفعيل ميزة "الاستلام داخل المتجر"، عليك إنشاء تطبيق للتعامل مع طلبات المنزل الذكي التالية:
-
IDENTIFY
: يتيح هذا الخيار العثور على الأجهزة الذكية التي يمكن التحكّم فيها محليًا. يستخرج معالج الإحالات المقصودة البيانات التي يعرضها جهازك الذكي أثناء عملية الاكتشاف ويرسلها في ردّ إلى Google. -
EXECUTE
: يتيح تنفيذ الطلبات. QUERY
: يتيح الاستعلام عن حالة الجهاز.-
REACHABLE_DEVICES
: (اختياري) يتيح اكتشاف devices الطرفية التي يمكن التحكّم فيها محليًا من خلال جهاز مركزي (أو جسر).
يعمل هذا التطبيق على أجهزة Google Home أو Google Nest الخاصة بالمستخدم ويربط جهازك الذكي بتطبيق مساعد Google. يمكنك إنشاء التطبيق باستخدام TypeScript (الخيار المفضّل) أو JavaScript.
ننصح باستخدام TypeScript لأنّه يمكنك الاستفادة من عمليات الربط للتأكّد بشكل ثابت من أنّ البيانات التي يعرضها تطبيقك تتطابق مع الأنواع التي تتوقّعها المنصة.
لمزيد من التفاصيل عن واجهة برمجة التطبيقات، يُرجى الاطّلاع على مرجع واجهة برمجة التطبيقات لـ Local Home SDK.
توضِّح المقتطفات التالية كيفية بدء تطبيق التسليم داخل المتجر وإرفاق معالِجاتك.
import App = smarthome.App; const localHomeApp: App = new App("1.0.0"); localHomeApp .onIdentify(identifyHandler) .onExecute(executeHandler) .listen() .then(() => { console.log("Ready"); });
import App = smarthome.App; const localHomeApp: App = new App("1.0.0"); localHomeApp .onIdentify(identifyHandler) .onReachableDevices(reachableDevicesHandler) .onExecute(executeHandler) .listen() .then(() => { console.log("Ready"); });
إنشاء مشروعك
لنشر تطبيقك المخصّص للتوصيل داخل المتجر، عليك إنشاء حِزمة JavaScript لرمزك البرمجي وجميع العناصر التي يعتمد عليها.
استخدِم مهيئ المشروع لتطبيق التنفيذ على الجهاز لتشغيل بنية المشروع المناسبة باستخدام الإعداد المفضّل لديك في أداة التجميع.
نماذج المشاريع
لاختيار إعدادات أداة التجميع، شغِّل الأمر npm init
كما هو موضّح في الأمثلة التالية:
TypeScript بدون إعداد أداة تجميع الحِزم:
npm init @google/local-home-app project-directory/ --bundler none
بنية المشروع:
project-directory/ ├── node_modules/ ├── package.json ├── .gitignore ├── index.ts ├── test.ts ├── tsconfig.json ├── tslint.json └── serve.js
استبدِل project-directory بدليل جديد سيحتوي على مشروع تطبيق التسليم المحلي.
TypeScript مع إعدادات أداة تجميع حزم webpack:
npm init @google/local-home-app project-directory/ --bundler webpack
بنية المشروع:
project-directory/ ├── node_modules/ ├── package.json ├── .gitignore ├── index.ts ├── test.ts ├── tsconfig.json ├── tslint.json ├── webpack.config.web.js ├── webpack.config.node.js └── serve.js
استبدِل project-directory بدليل جديد سيحتوي على مشروع تطبيق التسليم المحلي.
TypeScript مع إعدادات أداة تجميع حزم Rollup:
npm init @google/local-home-app project-directory/ --bundler rollup
بنية المشروع:
project-directory/ ├── node_modules/ ├── package.json ├── .gitignore ├── index.ts ├── test.ts ├── tsconfig.json ├── tslint.json ├── rollup.config.js └── serve.js
استبدِل project-directory بدليل جديد يحتوي على مشروع تطبيق التنفيذ المحلي.
TypeScript مع إعداد أداة تجميع Parcel:
npm init @google/local-home-app project-directory/ --bundler parcel
بنية المشروع:
project-directory/ ├── node_modules/ ├── package.json ├── .gitignore ├── index.ts ├── test.ts ├── tsconfig.json ├── tslint.json └── serve.js
استبدِل project-directory بدليل جديد سيحتوي على مشروع تطبيق التسليم المحلي.
تنفيذ المهام الشائعة على مستوى المشروع
يتيح المشروع الذي تم إنشاؤه استخدام npm scripts التالية:
cd project-directory/ npm run build
يُجمِّع هذا النص البرمجي مصدر TypeScript، ويجمِّع تطبيقك مع تبعياته لبيئة تشغيل Chrome في الدليل الفرعي dist/web
وبيئة تشغيل Node.js في الدليل الفرعي dist/node
.
cd project-directory/ npm run lint npm run compile npm test
يتحقّق هذا النص البرمجي من بنية رمز TypeScript، ويجمعه بدون إنشاء أيّ مخرجات في الدليل الفرعي dist/
، ويُجري اختبارات مبرمَجة من test.ts
.
cd project-directory/ npm run start
أثناء التطوير، يعرض هذا النص البرمجي حِزم تطبيقك لبيئات وقت تشغيل Chrome وNode.js على الجهاز.
تنفيذ معالِج IDENTIFY
سيتم تنشيط معالِج IDENTIFY
عند إعادة تشغيل جهاز Google Home أو Google Nest و
رصد الأجهزة المحلية غير التي تم التحقّق منها (بما في ذلك الأجهزة الطرفية المتصلة بوحدة تحكّم). ستبدأ منصّة
Local Home في البحث عن الأجهزة المحلية باستخدام معلومات إعدادات الفحص
التي حدّدتها سابقًا وستستدعي معالِج IDENTIFY
مع نتائج الفحص.
تتضمّن السمة
IdentifyRequest
من منصة الصفحة الرئيسية المحلية بيانات عملية المسح الضوئي لمثيل
LocalIdentifiedDevice
. يتمّ تعبئة مثيل واحد فقط من device
استنادًا إلى إعدادات الفحص
التي اكتشفت الجهاز.
إذا كانت نتائج الفحص تتطابق مع جهازك، من المفترض أن يعرض معالِج IDENTIFY
كائنًا
IdentifyResponsePayload
يتضمّن كائنًا device
يحتوي على
بيانات وصفية للمنزل الذكي (مثل الأنواع والسمات وحالة التقرير).
وينشئ محرّك بحث Google عملية ربط للجهاز إذا كانت قيمة verificationId
من استجابة IDENTIFY
تتطابق مع إحدى قيم otherDeviceIds
التي تعرضها استجابة SYNC
.
مثال
توضِّح المقتطفات التالية كيفية إنشاء معالِجات IDENTIFY
لتكامل
الأجهزة المستقلة والتكامل مع المحور، على التوالي.
const identifyHandler = (request: IntentFlow.IdentifyRequest): IntentFlow.IdentifyResponse => { // Obtain scan data from protocol defined in your scan config const device = request.inputs[0].payload.device; if (device.udpScanData === undefined) { throw Error("Missing discovery response"); } const scanData = device.udpScanData.data; // Decode scan data to obtain metadata about local device const verificationId = "local-device-id"; // Return a response const response: IntentFlow.IdentifyResponse = { intent: Intents.IDENTIFY, requestId: request.requestId, payload: { device: { id: device.id || "", verificationId, // Must match otherDeviceIds in SYNC response }, }, }; return response; };
const identifyHandler = (request: IntentFlow.IdentifyRequest): IntentFlow.IdentifyResponse => { // Obtain scan data from protocol defined in your scan config const device = request.inputs[0].payload.device; if (device.udpScanData === undefined) { throw Error("Missing discovery response"); } const scanData = device.udpScanData.data; // Decode scan data to obtain metadata about local device const proxyDeviceId = "local-hub-id"; // Return a response const response: IntentFlow.IdentifyResponse = { intent: Intents.IDENTIFY, requestId: request.requestId, payload: { device: { id: proxyDeviceId, isProxy: true, // Device can control other local devices isLocalOnly: true, // Device not present in `SYNC` response }, }, }; return response; };
تحديد الأجهزة المرتبطة بمركز
إذا رصدت Google جهازًا مركزيًا، ستتعامل معه على أنّه قناة عبور للأجهزة الطرفية المتصلة بالمركز وستحاول التحقّق من هذه الأجهزة الطرفية.
لكي تتمكّن Google من تأكيد توفّر جهاز وحدة تحكّم، اتّبِع تعليمات IDENTIFY
التالية:
- إذا كان ردّ
SYNC
يُبلغ عن أرقام تعريف الأجهزة الطرفية المحلية المتصلة بالبوابة، اضبطisProxy
علىtrue
فيIdentifyResponsePayload
. - إذا لم تُبلِغ استجابة
SYNC
عن جهاز الإرساء، اضبطisLocalOnly
علىtrue
فيIdentifyResponsePayload
. - يحتوي الحقل
device.id
على رقم تعريف الجهاز المحلي لجهاز المحور نفسه.
تنفيذ المعالِج REACHABLE_جرب (عمليات دمج المركز فقط)
ترسل Google هدف REACHABLE_DEVICES
لتأكيد الأجهزة النهائية التي يمكن التحكّم فيها محليًا. ويظهر هذا النية في كل مرة يُجري فيها محرّك بحث Google
عملية فحص استكشافية (مرة واحدة تقريبًا كل دقيقة)، طالما أنّ الموزع (Hub)
على الإنترنت.
يمكنك تنفيذ معالِج REACHABLE_DEVICES
بالطريقة نفسها التي تنفِّذ بها معالِج IDENTIFY
، باستثناء أنّ معالِجك يحتاج إلى جمع أرقام تعريف أجهزة إضافية
يمكن للوكيل المحلي (أي المحور) الوصول إليها. يحتوي الحقل
device.verificationId
على رقم تعريف الجهاز المحلي لجهاز نهائي
مرتبط بالمركز.
يتضمّن ReachableDevicesRequest
من منصّة الصفحة الرئيسية المحلية مثالاً على
LocalIdentifiedDevice
.
من خلال هذا المثيل، يمكنك الحصول على معرّف جهاز الخادم الوكيل بالإضافة إلى البيانات من
نتائج الفحص.
يجب أن يعرِض معالِج REACHABLE_DEVICES
عنصرًا
ReachableDevicesPayload
يتضمّن عنصرًا devices
يحتوي على صفيف من قيم
verificationId
تمثّل الأجهزة الطرفية التي يتحكّم فيها المحور. ويجب أن تتطابق قيم verificationId
مع إحدى otherDeviceIds
من الاستجابة SYNC
.
يوضّح المقتطف التالي طريقة إنشاء معالج REACHABLE_DEVICES
.
const reachableDevicesHandler = (request: IntentFlow.ReachableDevicesRequest): IntentFlow.ReachableDevicesResponse => { // Reference to the local proxy device const proxyDeviceId = request.inputs[0].payload.device.id; // Gather additional device ids reachable by local proxy device // ... const reachableDevices = [ // Each verificationId must match one of the otherDeviceIds // in the SYNC response { verificationId: "local-device-id-1" }, { verificationId: "local-device-id-2" }, ]; // Return a response const response: IntentFlow.ReachableDevicesResponse = { intent: Intents.REACHABLE_DEVICES, requestId: request.requestId, payload: { devices: reachableDevices, }, }; return response; };
تنفيذ معالِج EXECUTE
يعالج معالِج EXECUTE
في التطبيق أوامر المستخدمين ويستخدم
حزمة Local Home SDK للوصول إلى أجهزتك الذكية من خلال بروتوكول حالي.
تمرّر منصة "المنزل المحلي" حمولة الإدخال نفسها إلى وظيفة معالج EXECUTE
كما تنفّذ نية EXECUTE
المتعلقة بالتنفيذ على السحابة الإلكترونية. وبالمثل، يعرض معالِج EXECUTE
بيانات الإخراج بالتنسيق نفسه المستخدَم في معالجة طلب EXECUTE
.
لتبسيط عملية إنشاء الردود، يمكنك استخدام فئة Execute.Response.Builder
التي توفّرها حزمة تطوير البرامج للمنازل المحلية.
لا يمكن لتطبيقك الوصول مباشرةً إلى عنوان IP للجهاز. بدلاً من ذلك، يمكنك استخدام واجهة CommandRequest
لإنشاء أوامر استنادًا إلى أحد البروتوكولات التالية: UDP أو TCP أو HTTP. بعد ذلك، يمكنك طلب
الدالة deviceManager.send()
لإرسال الأوامر.
عند توجيه الأوامر إلى الأجهزة، استخدِم معرّف الجهاز (والمَعلمات من الحقل
customData
، إذا كان مضمّنًا) من استجابة SYNC
للتواصل
مع الجهاز.
مثال
يوضّح المقتطف التالي من الرمز البرمجي كيفية إنشاء معالِج EXECUTE
.
const executeHandler = (request: IntentFlow.ExecuteRequest): Promise<IntentFlow.ExecuteResponse> => { // Extract command(s) and device target(s) from request const command = request.inputs[0].payload.commands[0]; const execution = command.execution[0]; const response = new Execute.Response.Builder() .setRequestId(request.requestId); const result = command.devices.map((device) => { // Target id of the device provided in the SYNC response const deviceId = device.id; // Metadata for the device provided in the SYNC response // Use customData to provide additional required execution parameters const customData: any = device.customData; // Convert execution command into payload for local device let devicePayload: string; // ... // Construct a local device command over TCP const deviceCommand = new DataFlow.TcpRequestData(); deviceCommand.requestId = request.requestId; deviceCommand.deviceId = deviceId; deviceCommand.data = devicePayload; deviceCommand.port = customData.port; deviceCommand.operation = Constants.TcpOperation.WRITE; // Send command to the local device return localHomeApp.getDeviceManager() .send(deviceCommand) .then((result) => { response.setSuccessState(result.deviceId, state); }) .catch((err: IntentFlow.HandlerError) => { err.errorCode = err.errorCode || IntentFlow.ErrorCode.INVALID_REQUEST; response.setErrorState(device.id, err.errorCode); }); }); // Respond once all commands complete return Promise.all(result) .then(() => response.build()); };
تنفيذ معالج QUERY
يعالج معالِج QUERY
في التطبيق طلبات المستخدمين ويستخدم
حزمة Local Home SDK للإبلاغ عن حالة أجهزتك الذكية.
تمرِّر منصة الصفحة الرئيسية المحلية حمولة الطلب نفسها إلى وظيفة معالج "QUERY"
مثل نية QUERY
لتنفيذ الطلبات على السحابة الإلكترونية. وبالمثل، يعرض معالِج QUERY
البيانات
بالتنسيق نفسه المستخدَم في معالجة طلب QUERY
.
إرسال الأوامر إلى الأجهزة التي تتصل بمركز
للتحكم في الأجهزة النهائية الموجودة خلف الموزع (hub)، قد تحتاج إلى تقديم معلومات إضافية
في حمولة الأوامر الخاصة بالبروتوكول والتي تم إرسالها إلى الموزع (hub)
لتحديد الجهاز الذي يستهدفه الأمر. في بعض الحالات، يمكن استنتاج ذلك
مباشرةً من قيمة device.id
، ولكن إذا لم يكن الأمر كذلك،
عليك تضمين هذه البيانات الإضافية كجزء من حقل customData
.
إذا أنشأت تطبيقك باستخدام TypeScript، تذكَّر تجميع تطبيقك ليعمل باستخدام JavaScript. يمكنك استخدام نظام الوحدات الذي تختاره لكتابة التعليمة البرمجية. تأكَّد من توافق هدفك مع متصفّح Chrome.