لتفعيل ميزة "الاستلام داخل المتجر"، عليك إنشاء تطبيق للتعامل مع طلبات المنزل الذكي التالية:
-
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 لرمزك البرمجي وجميع العناصر التي يعتمد عليها.
استخدِم تطبيق التنفيذ المحلي project initializer لبدء بنية المشروع المناسبة باستخدام إعدادات أداة تجميع التطبيقات المفضّلة لديك.
نماذج المشاريع
لاختيار إعدادات أداة تجميع الحِزم، شغِّل الأمر 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
من منصة Local Home على بيانات المسح الضوئي لمثيل
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_DEVICES (عمليات دمج الموزّعين فقط)
تُرسِل Google طلب REACHABLE_DEVICES
لتأكيد الأجهزة الطرفية التي
يمكن التحكّم فيها محليًا. يتم بدء هذا الإجراء في كل مرة تُجري فيها Google عملية فحص
للاكتشاف (مرة واحدة تقريبًا كل دقيقة)، ما دام قد تم رصد أنّ المحور
متصل بالإنترنت.
يمكنك تنفيذ معالِج REACHABLE_DEVICES
بالطريقة نفسها التي تنفِّذ بها معالِج IDENTIFY
، باستثناء أنّ معالِجك يحتاج إلى جمع أرقام تعريف أجهزة إضافية
يمكن للوكيل المحلي (أي المحور) الوصول إليها. يحتوي الحقل
device.verificationId
على رقم تعريف الجهاز المحلي لجهاز نهائي
متصل بالمركز.
يحتوي ملف
ReachableDevicesRequest
من منصة Local Home على مثيل
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 للوصول إلى أجهزتك الذكية من خلال بروتوكول حالي.
تُرسِل منصة Local Home حمولة الإدخال نفسها إلى EXECUTE
دالة معالِج EXECUTE
بهدف تلبية الطلب في السحابة الإلكترونية. وبالمثل، يعرض معالِج EXECUTE
بيانات الإخراج بالتنسيق نفسه المستخدَم في معالجة طلب EXECUTE
.
لتبسيط عملية إنشاء الردّ، يمكنك استخدام فئة
Execute.Response.Builder
التي يوفّرها حزمة تطوير البرامج (SDK) لتطبيق Local Home.
لا يمكن لتطبيقك الوصول مباشرةً إلى عنوان 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 للإبلاغ عن حالة أجهزتك الذكية.
تُرسِل منصة Local Home حمولة الطلب نفسها إلى دالّة معالِج QUERY، كما هو الحال بالنسبة إلى QUERY
قصد تلبية الطلب في السحابة الإلكترونية. وبالمثل، يعرض معالِج QUERY
البيانات
بالتنسيق نفسه المستخدَم في معالجة طلب QUERY
.
إرسال الأوامر إلى الأجهزة التي تتصل بمركز
للتحكّم في الأجهزة الطرفية من خلال وحدة تحكّم، قد تحتاج إلى تقديم معلومات إضافية
في الحمولة الخاصة بالأمر الخاصة بالبروتوكول المُرسَلة إلى وحدة التحكّم
لتحديد الجهاز المقصود بالأمر. في بعض الحالات، يمكن استنتاج ذلك
مباشرةً من قيمة device.id
، ولكن عندما لا يكون الأمر كذلك،
عليك تضمين هذه البيانات الإضافية كجزء من حقل customData
.
إذا أنشأت تطبيقك باستخدام TypeScript، تذكَّر تجميع تطبيقك ليعمل باستخدام JavaScript. يمكنك استخدام نظام الوحدات الذي تختاره لكتابة الرمز. تأكَّد من أنّ المستهدَف متوافق مع متصفّح Chrome.