برنامه تحقق محلی را پیاده سازی کنید

برای پشتیبانی از تحقق محلی، باید برنامه ای بسازید تا این اهداف خانه هوشمند را مدیریت کند:

  • IDENTIFY : از کشف دستگاه های هوشمند قابل کنترل محلی پشتیبانی می کند. Intent handler داده‌هایی را که دستگاه هوشمند شما در حین کشف برمی‌گرداند استخراج می‌کند و در پاسخ به Google ارسال می‌کند.
  • EXECUTE : از اجرای دستورات پشتیبانی می کند.
  • QUERY : از وضعیت دستگاه پرس و جو پشتیبانی می کند.
  • REACHABLE_DEVICES : (اختیاری) از کشف دستگاه‌های انتهایی قابل کنترل محلی در پشت دستگاه هاب (یا پل) پشتیبانی می‌کند.

این برنامه روی دستگاه‌های Google Home یا Google Nest کاربر اجرا می‌شود و دستگاه هوشمند شما را به Assistant متصل می‌کند. می توانید برنامه را با استفاده از TypeScript (ترجیحا) یا JavaScript ایجاد کنید.

TypeScript توصیه می‌شود زیرا می‌توانید از اتصال‌ها برای اطمینان از اینکه داده‌هایی که برنامه شما برمی‌گرداند با انواع مورد انتظار پلتفرم مطابقت دارند، به‌طور ایستا استفاده کنید.

برای جزئیات بیشتر در مورد API، به مرجع Local Home SDK API مراجعه کنید.

قطعه‌های زیر نشان می‌دهند که چگونه می‌توانید برنامه تحقق محلی را مقداردهی اولیه کنید و کنترل‌کننده‌های خود را متصل کنید.

مستقل
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");
  });

پروژه خود را ایجاد کنید

به منظور استقرار برنامه تحقق محلی خود، باید یک بسته جاوا اسکریپت برای کد خود و همه وابستگی های آن بسازید.

برای راه‌اندازی ساختار پروژه مناسب با پیکربندی باندلر دلخواه خود، از راه‌انداز پروژه برنامه تحقق محلی استفاده کنید.

قالب های پروژه

برای انتخاب پیکربندی باندلر، دستور 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 با پیکربندی بسته‌بندی وب :

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 با پیکربندی باندلر جمع‌آوری :

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 با پیکربندی بسته‌کننده بسته :

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 زیر پشتیبانی می کند:

دسته
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

این اسکریپت نحو کد تایپ اسکریپت شما را تأیید می کند، آن را بدون تولید خروجی در دایرکتوری فرعی dist/ کامپایل می کند و تست های خودکار را از test.ts اجرا می کند.

خدمت
cd project-directory/
npm run start

در طول توسعه، این اسکریپت بسته‌های برنامه شما را برای محیط‌های زمان اجرا Chrome و Node.js به صورت محلی ارائه می‌کند.

کنترل کننده IDENTIFY را پیاده سازی کنید

وقتی دستگاه Google Home یا Google Nest راه‌اندازی مجدد شود و دستگاه‌های محلی تأیید نشده (از جمله دستگاه‌های پایانی متصل به هاب) را ببیند، کنترل‌کننده IDENTIFY فعال می‌شود. پلت فرم Local Home دستگاه های محلی را با استفاده از اطلاعات پیکربندی اسکن که قبلاً مشخص کرده اید اسکن می کند و با کنترل کننده IDENTIFY شما با نتایج اسکن تماس می گیرد.

IdentifyRequest از پلتفرم Local Home حاوی داده های اسکن یک نمونه LocalIdentifiedDevice است. فقط یک نمونه device پر شده است، بر اساس پیکربندی اسکن که دستگاه را کشف کرده است.

اگر نتایج اسکن با دستگاه شما مطابقت داشته باشد، کنترل کننده IDENTIFY شما باید یک شی IdentifyResponsePayload را برگرداند که شامل یک شی device با فراداده خانه هوشمند (مانند انواع، ویژگی ها و وضعیت گزارش) است.

اگر verificationId از پاسخ IDENTIFY با یکی از مقادیر otherDeviceIds برگردانده شده توسط پاسخ SYNC مطابقت داشته باشد، Google یک ارتباط دستگاه ایجاد می کند.

مثال

قطعه‌های زیر نشان می‌دهند که چگونه می‌توانید به ترتیب برای ادغام دستگاه‌های مستقل و هاب، کنترل‌کننده‌های 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 در IdentifyResponsePayload به عنوان true تنظیم کنید.
  • اگر پاسخ SYNC شما دستگاه هاب شما را گزارش نمی کند، isLocalOnly به عنوان true در IdentifyResponsePayload تنظیم کنید.
  • فیلد device.id حاوی شناسه محلی دستگاه برای خود دستگاه هاب است.

پیاده‌سازی کنترلر REACHABLE_DEVICES (فقط ادغام‌های هاب)

هدف REACHABLE_DEVICES توسط Google ارسال می‌شود تا تأیید کند کدام دستگاه‌های نهایی را می‌توان به صورت محلی کنترل کرد. این هدف هر بار که 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 که Local Home SDK ارائه می دهد استفاده کنید.

برنامه شما دسترسی مستقیم به آدرس 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 ایجاد کرده اید، به یاد داشته باشید که برنامه خود را به جاوا اسکریپت کامپایل کنید. برای نوشتن کد می توانید از سیستم ماژول انتخابی خود استفاده کنید. مطمئن شوید که هدف شما توسط مرورگر کروم پشتیبانی می شود.