লোকাল ফুলফিলমেন্ট অ্যাপ প্রয়োগ করা

লোকাল ফুলফিলমেন্টের জন্য, আপনাকে এইসব স্মার্ট হোম ইনটেন্ট ম্যানেজ করার জন্য অ্যাপ তৈরি করতে হবে:

  • IDENTIFY: স্থানীয়ভাবে কন্ট্রোল করা যায় এমন স্মার্ট ডিভাইস খুঁজে পেতে সাহায্য করে। ইনটেন্ট হ্যান্ডলার স্মার্ট ডিভাইস থেকে পাওয়া ডেটা এক্সট্র্যাক্ট করে এবং 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-এর পরিবর্তে নতুন ডিরেক্টরি ব্যবহার করুন যাতে লোকাল ফুলফিলমেন্ট অ্যাপ প্রোজেক্ট থাকবে।

Webpack

webpack বান্ডলার কনফিগারেশন সহ 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-এর পরিবর্তে নতুন ডিরেক্টরি ব্যবহার করুন যাতে লোকাল ফুলফিলমেন্ট অ্যাপ প্রোজেক্ট থাকবে।

রোলআপ

Rollup বান্ডলার কনফিগারেশন সহ 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-এর পরিবর্তে নতুন ডিরেক্টরি ব্যবহার করুন যাতে লোকাল ফুলফিলমেন্ট অ্যাপ প্রোজেক্ট থাকবে।

পার্সেল

Parcel বান্ডলার কনফিগারেশন সহ 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 সোর্স কম্পাইল করে এবং dist/web সাবডিরেক্টরিতে Chrome রানটাইম এনভায়রনমেন্ট এবং dist/node সাবডিরেক্টরিতে Node.js রানটাইম এনভায়রনমেন্টের জন্য আপনার অ্যাপকে তার ডিপেন্ডেন্সি সহ বান্ডেল করে।

যাচাই করুন
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 হ্যান্ডলার প্রয়োগ করুন

Google Home বা Google Nest ডিভাইস রিবুট হলে এবং যাচাই না করা স্থানীয় ডিভাইস (হাবের সাথে কানেক্ট করা এন্ড ডিভাইস সহ) দেখলে IDENTIFY হ্যান্ডলার ট্রিগার হবে। লোকাল হোম প্ল্যাটফর্ম, আপনার আগে উল্লেখ করা স্ক্যান কনফিগারেশন তথ্য ব্যবহার করে লোকাল ডিভাইস স্ক্যান করবে এবং স্ক্যান ফলাফল সহ আপনার IDENTIFY হ্যান্ডলারকে কল করবে।

Local Home প্ল্যাটফর্ম থেকে IdentifyRequest -এ LocalIdentifiedDevice ইনস্ট্যান্সের স্ক্যান ডেটা থাকে। স্ক্যান কনফিগারেশনের উপর ভিত্তি করে, শুধুমাত্র একটি device ইনস্ট্যান্স পপুলেট করা হয় যা ডিভাইসটি খুঁজে পেয়েছে।

স্ক্যান ফলাফল আপনার ডিভাইসের সাথে ম্যাচ করলে, আপনার IDENTIFY হ্যান্ডলারকে একটি IdentifyResponsePayload অবজেক্ট ফিরিয়ে দিতে হবে, যার মধ্যে স্মার্ট হোম মেটাডেটা (যেমন ধরন, বৈশিষ্ট্য এবং রিপোর্ট স্টেট) সহ একটি device অবজেক্ট থাকে।

Google একটি ডিভাইস অ্যাসোসিয়েশন তৈরি করে যদি IDENTIFY উত্তর থেকে পাওয়া verificationId, SYNC উত্তর থেকে পাওয়া otherDeviceIds ভ্যালুর মধ্যে কোনও একটির সাথে মিলে যায়।

উদাহরণ

নিম্নলিখিত স্নিপেট থেকে আপনি জানতে পারবেন যে কীভাবে স্ট্যান্ডঅ্যালোন ডিভাইস ও হাব ইন্টিগ্রেশনের জন্য 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 ফিল্ডে হাবের সাথে কানেক্ট করা এন্ড ডিভাইসের লোকাল ডিভাইস আইডি থাকে।

Local Home প্ল্যাটফর্মের ReachableDevicesRequest-এ LocalIdentifiedDevice-এর একটি ইনস্ট্যান্স আছে। এই ইনস্ট্যান্সের মাধ্যমে, আপনি প্রক্সি ডিভাইস আইডি এবং স্ক্যান ফলাফল থেকে ডেটা পেতে পারেন।

আপনার REACHABLE_DEVICES হ্যান্ডলারের একটি ReachableDevicesPayload অবজেক্ট রিটার্ন করা উচিত যার মধ্যে একটি devices অবজেক্ট থাকবে। এই অবজেক্টে verificationId মানের একটি অ্যারে থাকবে যা হাবের মাধ্যমে কন্ট্রোল করা এন্ড ডিভাইসকে দেখাবে। verificationId ভ্যালু অবশ্যই SYNC রেসপন্স থেকে otherDeviceIds-এর মধ্যে একটির সাথে মিলতে হবে।

নিম্নলিখিত স্নিপেট থেকে আপনি কীভাবে REACHABLE_DEVICES হ্যান্ডলার তৈরি করবেন তা দেখানো হয়েছে।

Hub
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 ইনটেন্ট প্রসেস করার মতো একই ফর্ম্যাটে আউটপুট ডেটা রিটার্ন করে। উত্তর তৈরি করার প্রসেস সহজ করতে, আপনি Local Home SDK-এর প্রদান করা Execute.Response.Builder ক্লাস ব্যবহার করতে পারেন।

আপনার অ্যাপের কাছে ডিভাইসের IP অ্যাড্রেসের সরাসরি অ্যাক্সেস নেই। পরিবর্তে, এইসব প্রোটোকলের মধ্যে কোনও একটির উপর ভিত্তি করে কমান্ড তৈরি করতে CommandRequest ইন্টারফেস ব্যবহার করুন: UDP, TCP, বা HTTP। তারপর, কমান্ড পাঠাতে deviceManager.send() ফাংশন কল করুন।

ডিভাইসে কমান্ড টার্গেট করার সময়, ডিভাইসের সাথে যোগাযোগ করতে SYNC রেসপন্স থেকে ডিভাইস আইডি (এবং customData ফিল্ড থেকে প্যারামিটার, যদি অন্তর্ভুক্ত থাকে) ব্যবহার করুন।

উদাহরণ

নিম্নলিখিত কোড স্নিপেট থেকে আপনি জানতে পারবেন যে কীভাবে আপনার 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 ইনটেন্ট প্রসেস করার মতো একই ফর্ম্যাটে ডেটা ফেরত দেয়।

হাবের পিছনে থাকা ডিভাইসে কমান্ড পাঠানো হচ্ছে

হাবের পিছনে থাকা এন্ড ডিভাইস কন্ট্রোল করতে, আপনাকে প্রোটোকল-নির্দিষ্ট কমান্ড পেলোডে অতিরিক্ত তথ্য দিতে হতে পারে যা হাবে পাঠানো হয় যাতে হাব শনাক্ত করতে পারে যে কোন ডিভাইসের জন্য কমান্ডটি পাঠানো হয়েছে। কিছু ক্ষেত্রে, এটি সরাসরি device.id ভ্যালু থেকে অনুমান করা যেতে পারে, তবে এটি না হলে, আপনাকে customData ফিল্ডের অংশ হিসেবে এই অতিরিক্ত ডেটা অন্তর্ভুক্ত করতে হবে।

আপনি TypeScript ব্যবহার করে অ্যাপ তৈরি করলে, অ্যাপটি JavaScript-এ কম্পাইল করতে ভুলবেন না। আপনার কোড লেখার জন্য আপনি নিজের পছন্দের মডিউল সিস্টেম ব্যবহার করতে পারেন। আপনার টার্গেট Chrome ব্রাউজারে কাজ করে কিনা তা দেখে নিন।