কনফিগারেশন এবং ক্রমাঙ্কন (কনক্যাল)

সফটওয়্যার-ডিফাইন্ড ভেহিকেল (SDV) প্ল্যাটফর্মের কনফিগারেশন অ্যান্ড ক্যালিব্রেশন সার্ভিস (ConCal) গাড়ির স্পেসিফিকেশন, দেশের নিয়মকানুন এবং গ্রাহকের অর্ডার করা ফিচার অনুযায়ী SDV সার্ভিসগুলো কনফিগার করার সুবিধা প্রদান করে। এই সার্ভিসটি SDV প্ল্যাটফর্মের একটি মৌলিক ভিত্তি, যা OEM-দের একই সার্ভিস কোড একাধিক গাড়ির মধ্যে পুনরায় ব্যবহার করতে দেয়। এটি সার্ভিসগুলোকে কনফিগার করার পাশাপাশি একাধিক উৎস (যেমন, ফ্যাক্টরিতে, সার্ভিস সেন্টারে, বা ক্লাউড থেকে) থেকে পুনরায় কনফিগার করার সুযোগ দেয়।

এসডিভি প্ল্যাটফর্মটি একটি নির্দিষ্ট গাড়ির সার্ভিস বান্ডেলগুলোর কনফিগারেশন এবং ক্যালিব্রেশনের জন্য সার্ভিস-ফেসিং এপিআই প্রদান করে। এই ইন্টারফেসটি ব্যবহার করে, ওইএম-রা তাদের নিজস্ব কনফিগারেশন এবং ক্যালিব্রেশন লজিক প্রয়োগ করতে পারে।

কনফিগারেশন এবং ক্যালিব্রেশন পরিষেবাতে নিম্নলিখিত প্রক্রিয়াগুলি অন্তর্ভুক্ত রয়েছে:

  • কনফিগারেশন হলো এমন একটি বিষয় যা একটি গাড়ির মৌলিক বৈশিষ্ট্য ও আচরণ নির্ধারণ করে এবং এটি গাড়ির অবস্থান, ব্যবহারকারীর বেছে নেওয়া অপশন বা দেশের নিয়মকানুনের মতো একাধিক বিষয়ের উপর নির্ভর করতে পারে। এটি নির্ধারণ করে যে গাড়ির বিভিন্ন কম্পোনেন্ট কীভাবে একে অপরের সাথে কাজ করবে এবং সফটওয়্যারের এমন সব সেটিংস ঠিক করে দেয় যা গাড়ির সার্বিক কার্যকারিতাকে প্রভাবিত করে, যেমন—সফটওয়্যারের বিভিন্ন সংস্করণ, নেটওয়ার্ক সংযোগ এবং প্রাথমিক পরিচালন সংক্রান্ত প্যারামিটার।

  • ক্যালিব্রেশন হলো এমন একটি প্রক্রিয়া যা সিস্টেমের প্যারামিটারগুলোকে তাদের পূর্বনির্ধারিত সীমার মধ্যে সূক্ষ্মভাবে সমন্বয় করে। উদাহরণস্বরূপ, ক্যালিব্রেশন সেন্সর এবং অ্যাকচুয়েটরের নির্ভুলতা ঠিক করে, দূষণ নিয়ন্ত্রণের জন্য ইঞ্জিনের কর্মক্ষমতা উন্নত করে এবং চালনার সুবিধা ও নিরাপত্তা ব্যবস্থার প্রতিক্রিয়াকে আরও উন্নত করে। কনফিগারেশন একটি যানবাহন কীভাবে কাজ করবে তার মৌলিক কাঠামো নির্ধারণ করে, আর ক্যালিব্রেশন সেই কাঠামোর মধ্যে এর আচরণকে অপ্টিমাইজ করে। যানবাহন যাতে দূষণ সংক্রান্ত নিয়মকানুন মেনে চলে, কর্মক্ষমতা সর্বোচ্চ করে, নিরাপত্তা বাড়ায় এবং সময়ের সাথে সাথে হওয়া ক্ষয়ক্ষতি পুষিয়ে নিতে পারে, তা নিশ্চিত করার জন্য উভয়ই অত্যন্ত গুরুত্বপূর্ণ।

একটি স্ট্যান্ডার্ড SDV-ব্যাপী ConCal API প্রদানের মাধ্যমে, আমরা SDV সার্ভিস বান্ডেলগুলোর বাস্তবায়ন সহজ করি, যার ফলে বিভিন্ন OEM-এর ভিন্ন ভিন্ন যানবাহনে চালানোর জন্য কনফিগারেশন এবং ক্যালিব্রেশন সক্ষমতা পুনরায় বাস্তবায়নের প্রয়োজন এড়ানো যায়।

স্থাপত্য

প্রতিটি সার্ভিস বান্ডেলের এক বা একাধিক কনফিগারেশন আর্টিফ্যাক্ট থাকতে পারে।

কনফিগারেশন আর্টিফ্যাক্ট

একটি কনফিগারেশন আর্টিফ্যাক্ট (config) এক বা একাধিক কনফিগারেশন প্যারামিটার এবং তাদের মান নিয়ে গঠিত। কনফিগারেশন হলো একটি সার্ভিস-নির্দিষ্ট প্রোটোবাফ মেসেজ, যার ফিল্ডগুলোর মধ্যে নেস্টেড প্রোটোবাফ মেসেজ (struct), ম্যাপ, অ্যারে, int, float, bool, bytes, বা string প্যারামিটার অন্তর্ভুক্ত থাকতে পারে।

// Example of a configuration message.
message SampleServiceBundleConfig
{
 bool bool_parameter = 1;
 int64 int_parameter = 2;
 float float_parameter = 3;
 string str_parameter = 4;
 repeated string list_parameter = 5;
 map<string, int32> map_parameter = 6;
 SomeNestedMessage nested_parameter = 7;
 SomeComplexMessage complex_parameter = 8;
 some.nested.package.SomeNestedMessage nested_package = 9;
 bytes bytes_parameter = 10;
}

কনফিগারেশন শনাক্তকারী

প্রতিটি কনফিগারেশনের একটি অনন্য শনাক্তকারী থাকে। এই শনাক্তকারীটি সার্ভিস বান্ডেল মালিকের সম্পূর্ণ ইনস্ট্যান্স নাম এবং একটি কনফিগারেশন নাম নিয়ে গঠিত। একটি কনফিগারেশন নাম অবশ্যই সহজে পাঠযোগ্য, প্রতিটি সার্ভিস বান্ডেলের জন্য অনন্য হতে হবে এবং 'সার্ভিস বান্ডেল নামকরণের নিয়মাবলী' -তে সংজ্ঞায়িত নামকরণের মান, যেমন ' shared ', private , diagnostics ' এবং calibration অনুসরণ করতে হবে।

সীমাবদ্ধতা:

  • ইনস্ট্যান্সের নামটি অবশ্যই একটি অক্ষর দিয়ে শুরু হতে হবে।
  • সমস্ত অক্ষর অবশ্যই ছোট হাতের অক্ষর বা হাইফেন হতে হবে।
  • নামে পরপর একাধিকবার হাইফেন ব্যবহার করা যাবে না।
  • কনফিগারেশন নামের শেষে হাইফেন থাকতে পারবে না।
  • কনফিগারেশনের নামটি ৪৮ অক্ষরের বেশি হতে পারবে না।
  • একই সার্ভিস বান্ডেলের জন্য একই ভিএম-এ কনফিগারেশনের নামগুলো অবশ্যই অনন্য হতে হবে।

26Q2-এর আগে, কনফিগারেশন আইডি নিম্নরূপভাবে সংজ্ঞায়িত করা হয়:

// Unique identifier for the config.
message ConfigId {
  // The FQIN of the service bundle that owns the configuration.
  com.sdv.google.sd_common.ServiceFqin service_fqin = 1;

  // The name of the config.
  string config_name = 2;
}

বুট করার সময় কনফিগারেশনের মালিক শুধুমাত্র তার কনফিগারেশনের স্কিমা এবং এর ডিফল্ট মানগুলো জানে। একটি বর্তমান গাড়ির জন্য সার্ভিস-বান্ডেলের আচরণ কাস্টমাইজ করতে হলে, মালিক সার্ভিস বান্ডেলটিকে তার স্কিমার সাথে ডিফল্ট কনফিগারেশনও রেজিস্টার করতে হয়।

ডিফল্ট কনফিগারেশনের নিবন্ধন এবং কাস্টমাইজড কনফিগারেশন পুনরুদ্ধার

চিত্র ১. ডিফল্ট কনফিগারেশনের নিবন্ধন এবং কাস্টমাইজড কনফিগারেশনের পুনরুদ্ধার।

এর ফলে OEM-রা সার্ভিস বান্ডেল একবার প্রয়োগ করে একাধিক গাড়িতে তা কার্যকর করতে পারে।

মোতায়েন

ConCal, SDV প্ল্যাটফর্মে এক বা একাধিক সার্ভার ইনস্ট্যান্স রক্ষণাবেক্ষণ করতে পারে। সার্ভিস বান্ডেলগুলোর উচিত নিকটতম ConCal সার্ভারটি খুঁজে বের করে ব্যবহার করা। উদাহরণস্বরূপ, যদি প্রতিটি ECU-এর জন্য একটি করে ConCal স্থাপন করা হয়, তবে একটি সার্ভিস বান্ডেলের উচিত একই ECU-তে চলমান ConCal ইনস্ট্যান্সটিতে অ্যাক্সেস পাওয়া। এর ফলে সার্ভিস বান্ডেলটি সময়মতো কনফিগারেশন সংগ্রহ করতে পারে। যদি কোনো ConCal ইনস্ট্যান্সে অনুরোধ করা কনফিগারেশনটি না থাকে (কারণ এটি অন্য একটি ConCal-এর দায়িত্বাধীন এলাকার অন্তর্গত), তবে যোগাযোগ করা ConCal সার্ভারটি তার মালিক ConCal ইনস্ট্যান্সের কাছ থেকে সেটি অনুরোধ করে এবং সার্ভিস বান্ডেলের কাছে পাঠিয়ে দেয়।

কনফিগারেশন কাস্টমাইজেশন

বিভিন্ন যানবাহনে একই সফটওয়্যার পুনরায় ব্যবহার করার ক্ষমতা হলো এসডিভি-এর অন্যতম প্রধান সুবিধা। সফটওয়্যারটি একবার তৈরি করা হয় এবং তারপর একাধিক যানবাহনে পুনরায় ব্যবহার করা হয়, এবং আমরা গাড়ির নির্দিষ্ট বৈশিষ্ট্যের উপর ভিত্তি করে সফটওয়্যারটির আচরণ সামঞ্জস্য করতে পারি। এটাই কনক্যাল (ConCal)-এর মূল উদ্দেশ্য, যা কনফিগারেশন ওভাররাইডের সাহায্যে গাড়ির বৈশিষ্ট্যের উপর ভিত্তি করে সার্ভিস কনফিগারেশন গণনা করে।

ConfigOverride হলো একটি প্রোটোবাফ মেসেজ যা নির্দিষ্ট গাড়ির জন্য কনফিগারেশন কীভাবে সামঞ্জস্য করতে হবে তা বর্ণনা করে। এটি একটি ওভাররাইড আইডি (যা প্রদানকারী সত্তা দ্বারা অনন্যভাবে সংজ্ঞায়িত হয়), একটি কনফিগারেশন আইডেন্টিফায়ার এবং ConfigOverrideKeyValuePair এর একটি তালিকা নিয়ে গঠিত। ConfigOverride শুধুমাত্র আপডেট প্রক্রিয়ার সময় এবং শুধুমাত্র অনুমোদিত পরিষেবাগুলো দ্বারা প্রদান করা যেতে পারে, যা OEM দ্বারা মডেল করা হয়। উভয় কাঠামোর জন্য প্রোটোবাফ সংজ্ঞা নিচে দেওয়া হলো।

// Key-value pair to update configuration.
message ConfigOverrideKeyValue {
  string key = 1;

  oneof value {
    string value_txtproto = 2;
    .google.protobuf.Any value_any = 3;
  }
}

// A collection of changes for a specific configuration which should be atomically applied.
message ConfigOverride {
  string override_id = 1;

  ConfigId config_id = 2;

  repeated ConfigOverrideKeyValue pairs = 3;
}

ConfigOverride নিম্নলিখিত অপারেশনগুলো সমর্থন করে:

  • নতুন মান নির্ধারণ করুন: শেষ মানটি অপ্রচলিত হয়ে গেলে প্যারামিটারটিকে একটি নতুন মান দেওয়া হয়, যেমন একটি সাধারণ ফিল্ডে (int, string, float, bool, bytes) নতুন মান নির্ধারণ করা অথবা ম্যাপ, লিস্ট, স্ট্রাক্ট বা একটি সম্পূর্ণ কনফিগারেশনের মতো জটিল ফিল্ডগুলোকে নতুন করে লেখা।

  • মান অপসারণ বা পরিষ্কার করা: এই অপারেশনটি মেসেজ, রিপিটেড ফিল্ড, ম্যাপ, সিঙ্গুলার ফিল্ড এবং স্বয়ং কনফিগারেশন সহ সকল প্রকারের জন্য উপলব্ধ। এই অপারেশনটি একটি সম্পূর্ণ ফিল্ড বা মেসেজের উপর সম্পাদন করা যেতে পারে, যার অর্থ হলো একটি ম্যাপ থেকে নির্দিষ্ট কী এবং একটি রিপিটেড ফিল্ড থেকে স্বতন্ত্র উপাদান অপসারণ করা সমর্থিত নয়।

  • মানচিত্রে একটি নতুন মান যোগ করুন।

  • ম্যাপের কোনো বিদ্যমান কী-এর মান পুনরায় লিখুন (যদি কী-টি বিদ্যমান না থাকে, তবে এই কাজটি ম্যাপে একটি নতুন মান যোগ করা হিসাবেও করা যেতে পারে)।

ConCal ব্যবহার করে একটি পরিষেবা বান্ডেল কনফিগার করুন

এই অধ্যায়ে বর্ণনা করা হয়েছে কীভাবে এমন একটি সার্ভিস বান্ডেল তৈরি করতে হয় যা রানটাইমে তার কনফিগারেশন সংগ্রহ করে। একটি কনফিগারযোগ্য বান্ডেলের দৃষ্টিকোণ থেকে, এটি সম্পূর্ণ অস্পষ্ট যে সংগৃহীত কনফিগারেশনটি একটি ডিফল্ট ফ্যাক্টরি সেটিং, নাকি ConCal ওভাররাইডিং এবং ক্যালিব্রেশন প্রক্রিয়া ব্যবহার করে পরবর্তীকালে করা কোনো পরিবর্তন।

যে নমুনাটির উপর ভিত্তি করে ডকুমেন্টেশনটি তৈরি করা হয়েছে, সেটি আপনি system/software_defined_vehicle/samples/concal/src/concal_client -এ খুঁজে পাবেন।

আরও বিস্তারিত জানতে সার্ভিস বান্ডেল ডেভেলপমেন্ট দেখুন।

সার্ভিস বান্ডেলের মালিকানাধীন কনফিগারেশনের ধরণ ঘোষণা করুন।

সার্ভিস বান্ডেলটি যে কনফিগারেশন সংগ্রহ করে, তার ধরনের মালিকানা তারই থাকে। এর ফলে একটি কনফিগারযোগ্য বান্ডেলকে সংরক্ষিত কনফিগারেশন ডেটা থেকে স্বাধীনভাবে আপডেট করা যায়।

  1. কনফিগারেশন টাইপ ঘোষণা করে একটি প্রোটোবাফ ফাইল ( .proto এক্সটেনশন সহ) লিখুন:

    syntax = "proto3";
    
    package android.sdv.demo.config;
    
    message RearViewCamera {
    string model = 1;
    uint64 horizontal_resolution = 2;
    uint64 vertical_resolution = 3;
    float x_axis_field_of_view = 4;
    float y_axis_field_of_view = 5;
    bool is_rgb = 6;
    }
    
  2. একটি বিল্ড টার্গেট তৈরি করুন যা কনফিগারেশন টাইপ পুনরুদ্ধারের অনুমতি দেয় এমন রানটাইম লাইব্রেরি তৈরি করে। একটি Android.bp ফাইলে:

    rust_protobuf {
        name: "libsdvtestconcal_proto_rust",
        crate_name: "sdvtestconcal_proto_rust",
        protos: [
            "rear_view_camera.proto",
        ],
        proto_flags: [
            "-I external/protobuf/src",
            "-I .",
        ],
        source_stem: "sdvtestconcal_proto_rust",
        vendor_available: true,
        product_available: true,
        min_sdk_version: "35",
    }
    

আপনার বান্ডেলের জন্য ConCal RPC মিডলওয়্যার কোড তৈরি করুন

সার্ভিস বান্ডেলে একটি VSIDL ডিক্লারেশন যোগ করুন:

package: "com.sdv.oem.sample.concal"

service_bundle {
  name: "SampleOemConCalClientServiceBundle"
  client {
    service: "com.sdv.google.concal.ConCalRegistrationService"
  }
}

এর মাধ্যমে ঘোষণা করা হচ্ছে যে, এই বান্ডেলটি ConCal কনফিগারেশন নিবন্ধন ও পুনরুদ্ধার পরিষেবার একটি ক্লায়েন্ট। বান্ডেলটির জন্য RPC ক্লায়েন্ট বাইন্ডিং তৈরি করতে VSIDLC ব্যবহারের একটি সার্বিক ধারণা পেতে VSIDL এবং মিডলওয়্যার ওভারভিউ দেখুন।

RPC কনফিগারেশন পুনরুদ্ধারের জন্য মিডলওয়্যার শুরু করুন

রান টাইমে, ConCal RPC কলের জন্য প্রয়োজনীয় মিডলওয়্যার কম্পোনেন্টগুলো ইনিশিয়ালাইজ করুন। এই উদাহরণে, বান্ডেলটি চালু হওয়ার সময় আমরা অ্যাসিঙ্ক্রোনাসভাবে এগুলো ইনিশিয়ালাইজ করি।

pub struct ExampleConcalBundle {
    context: ContextRef,
    runtime: Option<Runtime>,
}

sdv::lifecycle::register_service_bundle!(ExampleConcalBundle);

impl ServiceBundle for ExampleConcalBundle {
    fn new(context: ContextRef) -> ExampleConcalBundle {
        info!("Creating {}.", context.get_self_fqin());

        ExampleConcalBundle { context, runtime: None }
    }

    fn on_start(&mut self) {
        let fqin = self.context.get_self_fqin();
        info!("Starting {}.", fqin);

        let runtime = Builder::new_multi_thread()
            .worker_threads(4)
            .thread_name("tokio-pool")
            .enable_all()
            .build()
            .unwrap();
        let context = self.context;
        runtime.spawn(async move {
            let registration_client = setup_register_config_rpc(context).await;
            /* main SB logic here */
        });
        self.runtime = Some(runtime);
    }

async fn setup_register_config_rpc(context: ContextRef) -> RegistrationClient {
    let sdv_comms = SdvComms { context };
    let sd = ServiceDiscoveryManager::new(context);
    let unit_name_args = UnitNameDiscoveryArgs::new_builder()
        .set_sdv_package_name("com.sdv.oem.sample.concal")
        .set_service_bundle_name("SampleOemConCalServiceBundle")
        .set_service_unit_name(RegistrationClient::DEFAULT_UNIT_NAME)
        .build()
        .unwrap();

    let mut unit_name_stream =
        sd.subscribe_service_unit_change_by_name(&unit_name_args).await.unwrap();

    // wait until RPC servers are registered, if server is not a custom agent
    while let Some(event) = unit_name_stream.next().await {
        if let ServiceUnitChangeEvent::Registered(sud) = event {
            let service_identity = sud.get_service_bundle_identity();
            let fqin = service_identity.get_fqin();
            if fqin.get_sdv_package_name() == "com.sdv.oem.sample.concal"
                && fqin.get_service_bundle_name() == "SampleOemConCalServiceBundle"
                && fqin.get_service_instance_name() == "default"
            {
                break;
            }
        }
    }

    let service_bundle =
        SampleOemConCalClientServiceBundle::new(Arc::new(sdv_comms)).await.unwrap();
    service_bundle
        .create_rpc_client::<RegistrationClient>(
            UnitName::builder()
                .package_name("com.sdv.oem.sample.concal")
                .bundle_name("SampleOemConCalServiceBundle")
                .service_unit_name(RegistrationClient::DEFAULT_UNIT_NAME)
                .build()
                .unwrap(),
            ClientOptions::default(),
        )
        .await
        .expect("Failed to create an RPC client")
}

কোথায়:

  • on_start এ, আমরা একটি টোকিও রানটাইম তৈরি করি এবং একটি টোকিও টাস্ক চালু করি। টাস্কটি বান্ডেল মেইন লজিকের কাজ শুরু করার আগে setup_register_rpc কে কল করে।
  • setup_register_rpc মিডলওয়্যার RPC বাইন্ডিং সেট আপ করে। উল্লেখ্য যে, উদাহরণটিতে ধরে নেওয়া হয়নি যে ConCal কার্যকারিতা কোনো এজেন্ট দ্বারা বাস্তবায়িত হয়েছে: সার্ভারটি বান্ডেলটি চালু হওয়ার পরেই কেবল উপলব্ধ হতে পারে। তাই, উদাহরণ কোডটি সার্ভিস ডিসকভারি এপিআই (Service Discovery API) ব্যবহার করে RPC সার্ভারটি নিবন্ধিত হওয়ার জন্য অপেক্ষা করে।

কনফিগারেশন শুরু করুন

ConCal সার্ভারকে একটি আইডি, কনফিগারেশন স্কিমা এবং ডিফল্ট, ফ্যাক্টরি কনফিগারেশন মান প্রদান করে কনফিগারেশন আর্টিফ্যাক্টটি রেজিস্টার করুন।

প্রথমবার রেজিস্ট্রেশন কল করা হলে, ডিফল্ট মানটি সংরক্ষিত থাকে। পরবর্তী বান্ডেল স্টার্টে রেজিস্ট্রেশন কল করা হলে, প্রয়োগকৃত ConCal ওভাররাইড (যদি থাকে) সহ সংরক্ষিত ডিফল্ট মানটি পুনরুদ্ধার করা হবে।

আর্টিফ্যাক্টটি আগে থেকে নিবন্ধিত আছে কি না, তা নির্বিশেষে ConCal রেজিস্টার কনফিগারেশন কলটি কখনোই ব্যর্থ হয় না।

impl ServiceBundle for ExampleConcalBundle{

    /* ... */
    fn on_start(&mut self) {
        /* ... */
        runtime.spawn(async move {
            let registration_client = setup_register_config_rpc(context).await;
            sample_concal_main(fqin, registration_client).await
        });
        self.runtime = Some(runtime);
    }
}

async fn sample_concal_main(
    fqin: ServiceFqin,
    registration_client: RegistrationClient,
) -> sdv::status::SdvResult<()> {
    let config = get_rear_view_camera_factory_config();
    let config_id = get_config_id(&fqin);

    register_config(&registration_client, &config_id, &config).await;
    /* ... */
}

fn get_rear_view_camera_factory_config() -> RearViewCamera {
    RearViewCamera {
        model: String::from("model 1"),
        horizontal_resolution: 720,
        vertical_resolution: 720,
        x_axis_field_of_view: 70.0,
        y_axis_field_of_view: 70.0,
        is_rgb: false,
        ..Default::default()
    }
}

fn get_config_id(fqin: &ServiceFqin) -> ConfigId {
    ConfigId {
        config_name: "config".to_string(),
        service_fqin: MessageField::some(ProtoFqin {
            vm_name: fqin.get_sdv_vm_name().to_string(),
            package_name: fqin.get_sdv_package_name().to_string(),
            service_name: fqin.get_service_bundle_name().to_string(),
            instance_name: fqin.get_service_instance_name().to_string(),
            ..Default::default()
        }),
        ..Default::default()
    }
}

async fn register_config(
    client: &RegistrationClient,
    config_id: &ConfigId,
    config: &RearViewCamera,
) {
    let config_fd = FileDescriptorSet {
        file: vec![RearViewCamera::descriptor().file_descriptor_proto().clone()],
        ..Default::default()
    };
    let config = Any::pack(config).expect("Failed to pack config");
    let config_metadata = ConfigMetadata {
        descriptor_set: MessageField::some(config_fd),
        default_config: MessageField::some(config.clone()),
        ..Default::default()
    };

    client
        .RegisterConfigMetadata(&RegisterConfigMetadataRequest {
            config_id: MessageField::some(config_id.clone()),
            metadata: MessageField::some(config_metadata),
            config_version: String::from("1.0"),
            ..Default::default()
        })
        .await
        .expect(
            "RegisterConfigMetadata should not fail, even if configuration was registered before",
        );
}

কোথায়:

  • on_start এ তৈরি হওয়া টাস্কটি, RPC বাইন্ডিং পুনরুদ্ধার করার পর, sample_concal_main কল করে বিজনেস লজিক নিয়ে এগিয়ে যায়।
  • sample_concal_main একটি কনফিগারেশন আর্টিফ্যাক্ট নিবন্ধন করার মাধ্যমে শুরু হয়। এর লজিক register_config এ অন্তর্ভুক্ত থাকে।
  • একটি কনফিগারেশন নিবন্ধন করতে, একটি বান্ডেলকে অবশ্যই তার প্রোটোবাফ টাইপ, একটি আইডি এবং একটি ডিফল্ট মান নির্দিষ্ট করতে হবে।
  • config_fd হলো কনফিগারেশন টাইপ। যে বান্ডেলটি এই কনফিগারেশন টাইপের মালিক, সেটি নিশ্চিত করে যে বান্ডেলের জন্য প্রত্যাশিত স্কিমাটি সর্বদা পুনরুদ্ধার করা হয়, যার মধ্যে APEX আপডেটের পরেও অন্তর্ভুক্ত।
  • কনক্যাল সার্ভারের অভ্যন্তরীণ ডেটা সংরক্ষণের লজিকে আইডিটি একটি শনাক্তকারী হিসেবে ব্যবহৃত হয়।
  • ডিফল্ট মানটি get_rear_view_camera_factory_config এ তৈরি করা হয়। যদি আগে কিছু সংরক্ষণ করা না হয়ে থাকে, তবে ConCal সার্ভার দ্বারা সংরক্ষিত মানটিই ডিফল্ট মান হিসেবে গণ্য হয়। এটি সিস্টেমের ফ্যাক্টরি কনফিগারেশন নির্দিষ্ট করার একটি উপায়। অন্যান্য সেটআপও সম্ভব।

কনফিগারেশন পুনরুদ্ধার করুন

নিবন্ধনের পরে, কনফিগারেশনটি পুনরুদ্ধার করুন। যেহেতু কনফিগারেশনটি আগে থেকেই নিবন্ধিত ছিল, তাই এই কলটি সফল হবেই।

async fn sample_concal_main(
    fqin: ServiceFqin,
    registration_client: RegistrationClient,
    update_client: UpdateClient,
) -> sdv::status::SdvResult<()> {
    let config = get_rear_view_camera_factory_config();
    let config_id = get_config_id(&fqin);

    register_config(&registration_client, &config_id, &config).await;
    let config = get_config(&registration_client, &config_id).await;
    info!("Retrieved configuration:\n{config:#?}");

    // Onwards, use configuration in bundle's main business logic
    /* ... */
}

async fn get_config(client: &RegistrationClient, config_id: &ConfigId) -> RearViewCamera {
    let bytes = client
        .GetConfig(&GetConfigRequest {
            config_id: MessageField::some(config_id.clone()),
            ..Default::default()
        })
        .await
        .expect("Get config does not fail, as config was registered before")
        .config;
    RearViewCamera::parse_from_bytes(&bytes).expect("parse_from_bytes failed")
}

কোথায়:

  • GetConfigRequest এর কলটি সফল হবেই, কারণ কনফিগারেশনটি পূর্বেই একই বান্ডেল দ্বারা নিবন্ধিত হয়েছিল। সেটআপ সার্ভিস বান্ডেলকে ফ্যাক্টরি কনফিগারেশন এবং ওভাররাইড করা কনফিগারেশন উভয় ক্ষেত্রেই অস্বচ্ছভাবে পরিচালনা করার সুযোগ দেয়: সার্ভিস বান্ডেলের ব্যবসায়িক যুক্তি অপরিবর্তিত থাকে।

  • GetConfigRequest কলটি র ডেটা বাইট হিসেবে ফেরত দেয়। get_config ফাংশনটি সেগুলোকে পার্স করে প্রত্যাশিত কনফিগারেশন টাইপে রূপান্তর করে।