ব্যবহারকারীর পছন্দের স্থাপত্য এবং বাস্তবায়ন নির্দেশিকা

এই পৃষ্ঠায় এসডিভি ইউজার প্রেফারেন্সেস সিস্টেমের স্থাপত্যের উপর একটি নির্দেশিকা এবং একটি ব্যবহারকারী-নিয়ন্ত্রণযোগ্য পরিষেবা ও ক্লায়েন্ট বাস্তবায়নের নির্দেশাবলী প্রদান করা হয়েছে।

স্থাপত্যের সংক্ষিপ্ত বিবরণ

ব্যবহারকারীর পছন্দ ব্যবস্থাটি ব্যবহারকারীর সেটিংসের সংরক্ষণ ও ব্যবস্থাপনাকে, সেই সেটিংসের প্রয়োগ ও বলবৎকরণ থেকে পৃথক করে। মূল স্থাপত্যগত পরিভাষাগুলো সারণিতে সংক্ষেপে তুলে ধরা হলো:

বৈশিষ্ট্য বর্ণনা ভূমিকা দায়িত্ব
ব্যবহারকারী-নিয়ন্ত্রণযোগ্য পরিষেবা একটি স্ট্যান্ডার্ড SDV সার্ভিস বান্ডেল যা একটি নির্দিষ্ট ডোমেইন পরিচালনা করে (যেমন, HVAC, গাড়ির সিট, অডিও)। এটি যে হার্ডওয়্যার বা সাবসিস্টেমকে নিয়ন্ত্রণ করে, তার সক্ষমতা ও সীমাবদ্ধতার উদ্দিষ্ট অবস্থা প্রদান করে।
  • নিবন্ধন: ব্যবহারকারীর পছন্দ নির্ধারণকারী এজেন্টকে তার সমর্থিত সেটিংস (মেটাডেটা, ডিফল্ট, সীমাবদ্ধতা) সম্পর্কে অবহিত করে।
  • প্রয়োগ ও স্বায়ত্তশাসন: সেটিংস পরিবর্তনের অনুরোধ গ্রহণ করে, বর্তমান অবস্থা ও সুরক্ষা নিয়মের সাথে সেগুলোকে যাচাই করে এবং হার্ডওয়্যারে প্রয়োগ করে। সম্পূর্ণ স্বায়ত্তশাসন বজায় রাখে এবং কোনো সেটিংস পরিবর্তন গৃহীত হবে নাকি প্রত্যাখ্যাত হবে, তা নির্দিষ্ট করে।
ব্যবহারকারীর পছন্দ এজেন্ট কেন্দ্রীয় নিয়ন্ত্রক কেন্দ্রীভূত স্টোরেজ, ব্যবহারকারীর প্রোফাইল ব্যবস্থাপনা এবং নোটিফিকেশন হাব প্রদান করে।
  • সংরক্ষণ: ব্যবহারকারী অনুযায়ী সেটিংস সংরক্ষণ করে (যেমন, চালক, যাত্রী)।
  • রাউটিং: প্রক্সিগুলো ক্লায়েন্ট (যেমন, হিউম্যান মেশিন ইন্টারফেস (HMI)) থেকে আসা অনুরোধগুলোকে উপযুক্ত ব্যবহারকারী-নিয়ন্ত্রণযোগ্য পরিষেবাতে পরিবর্তন করে।
  • বিজ্ঞপ্তি: ChangeNotifier ইন্টারফেস ব্যবহার করে আগ্রহী পক্ষগুলোর (ভিউ বা HMI) কাছে পরিবর্তনগুলো প্রচার করে।
  • ব্যবহারকারী ব্যবস্থাপনা: ব্যবহারকারী পরিবর্তন এবং সমস্ত নিবন্ধিত পরিষেবাগুলিতে সঠিক স্থায়ী অবস্থা প্রয়োগ করা পরিচালনা করে।
ব্যবহারকারীর পছন্দ ক্লায়েন্ট একটি অ্যাপ বা পরিষেবা যা একটি ইউজার ইন্টারফেস প্রদান করে, উদাহরণস্বরূপ, একটি HMI সহ IVI অ্যাপ অথবা অন্য কোনো লজিক যা ব্যবহারকারীর পছন্দের সাথে ইন্টারঅ্যাক্ট করতে চায়। ব্যবহারকারীদের সাথে যোগাযোগ করে, সেটিংস প্রদর্শন করে এবং পরিবর্তনের অনুরোধ শুরু করে।
  • প্রদর্শন: ব্যবহারকারীর কাছে বর্তমান সেটিংস ও সীমাবদ্ধতাগুলো উপস্থাপন করে।
  • পরিবর্তনের অনুরোধ: ব্যবহারকারীর উদ্যোগে করা সেটিং পরিবর্তনের অনুরোধ ইউজার প্রেফারেন্স এজেন্টের কাছে পাঠায়।
  • বিজ্ঞপ্তি গ্রহণ করুন: সেটিংসের রিয়েল-টাইম আপডেট পেতে এবং সে অনুযায়ী প্রতিক্রিয়া জানাতে সাবস্ক্রাইব করে।

ব্যবহারকারী-নিয়ন্ত্রণযোগ্য পরিষেবা বাস্তবায়ন করুন

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

ইউজার প্রেফারেন্সেস (এবং এইচএমআই সহ একজন ব্যবহারকারী)-কে আপনার পরিষেবা নিয়ন্ত্রণ করার সুযোগ দিতে এই বিভাগের ধাপগুলি অনুসরণ করুন।

  1. VSIDL ফাইলে সার্ভিস ইন্টারফেসগুলো সংজ্ঞায়িত করুন:

    • সার্ভার হিসেবে com.sdv.google.user_preferences.user_controllable.UserControllableService ইমপ্লিমেন্ট করুন। এটি এজেন্টকে আপনার কাছে পরিবর্তনের অনুরোধ পাঠাতে সক্ষম করে।
    • ক্লায়েন্ট হিসেবে, com.sdv.google.user_preferences.UserPreferencesRegistryService ব্যবহার করুন। এটি স্টার্টআপের সময় আপনার সেটিংস রেজিস্টার করে।

    নিম্নলিখিত উদাহরণটি একটি ব্যবহারকারী-নিয়ন্ত্রণযোগ্য পরিষেবার জন্য service_bundle.vsidl দেখাচ্ছে:

    service_bundle {
        name: "MyFeatureService"
        server {
            service: "com.sdv.google.user_preferences.user_controllable.UserControllableService"
        }
        client {
            service: "com.sdv.google.user_preferences.UserPreferencesRegistryService"
        }
    }
    
  2. user_preferences_registry_service.proto প্রোটো কী-তে স্টার্টআপের সময় সেটিংস নিবন্ধন করুন:

    1. UserPreferencesRegistryService এর সাথে সংযোগ করুন।
    2. RegisterSettingsRequest এর একটি ইনস্ট্যান্স তৈরি করুন।
    3. SettingsGroup (সেটিংসের একটি যৌক্তিক সংগ্রহ)-এর একটি ইনস্ট্যান্স সংজ্ঞায়িত করুন।
    4. প্রতিটি সেটিং-এর জন্য, সংজ্ঞায়িত করুন:

      *   **Key:** Unique string ID (for example, `TEMPERATURE`)
      *   **Kind:** `PER_USER` (stored per user profile) or `SHARED`
          (global)
      *   **Default value:** Initial value if no user preference exists
      *   **Constraints:** (optional) Validation rules (for example, Min
          16, Max 32 for HVAC).
      
    5. RegisterSettings() কল করুন।

    নিম্নলিখিত উদাহরণটি ধারণাগত রাস্ট-এ লেখা:

    let temperature_setting = SettingDefinition {
        name: "TEMPERATURE".to_string(),
        kind: SettingKind::PER_USER.into(),
        default_value: Value::Int64(22), // Default 22 degrees
        constraint: Some(Constraints::Int64Constraints(Int64Constraints {
            min_value: Some(16),
            max_value: Some(32),
            ..Default::default()
        })),
        ..Default::default()
    };
    
    registry_client.RegisterSettings(&RegisterSettingsRequest {
        group_name: "HVAC".to_string(),
        version: "1.0".to_string(),
        settings_definitions: vec![temperature_setting],
    }).await?;
    
  3. user_controllable_service.proto তে সেটিংস পরিবর্তনের অনুরোধগুলি পরিচালনা করুন:

    1. RequestSettingsChange RPC-টি বাস্তবায়ন করুন।
    2. অনুরোধকৃত মানগুলি বর্তমান প্রেক্ষাপটে বৈধ কিনা তা যাচাই করুন (উদাহরণস্বরূপ, হার্ডওয়্যারটি প্রস্তুত আছে কিনা)।
    3. পরিবর্তনটি প্রয়োগ করতে নির্দিষ্ট লজিক ব্যবহার করুন (যেমন, সিট সরানো, ফ্যানের গতি পরিবর্তন করা)।
    4. RequestSettingsChangeResponse এ প্রয়োগকৃত মানগুলি ফেরত দিন:
    5. আপনি যদি পরিবর্তনটি গ্রহণ করে থাকেন, তাহলে নতুন মানটি ফেরত দিন।
    6. যদি আপনি মানটি প্রত্যাখ্যান বা সীমাবদ্ধ করে থাকেন, তাহলে আপনার সেট করা (বা রাখা) মানটি ফেরত দিন।

    নিম্নলিখিত উদাহরণটি ধারণাগত রাস্ট-এ লেখা:

    async fn RequestSettingsChange(
        &self,
        _caller_id: ServiceFqin,
        request: &RequestSettingsChangeRequest
    ) -> SdvResult<RequestSettingsChangeResponse> {
        let mut applied_settings = Vec::new();
    
        for setting in &request.settings {
            if self.hardware.set_value(setting.key, setting.value).is_ok() {
                // Change accepted
                applied_settings.push(setting.clone());
            } else {
                // Change rejected, return current actual value
                let current_val = self.hardware.get_value(setting.key);
                applied_settings.push(create_setting(setting.key, current_val));
            }
        }
    
        Ok(RequestSettingsChangeResponse {
            settings: applied_settings,
        })
    }
    
  4. আপনার সাবসিস্টেমকে একটি পরিষ্কার অবস্থায় ফিরিয়ে আনতে FactoryReset RPC প্রয়োগ করুন:

    1. সমস্ত সেটিংসকে তাদের ডিফল্ট মানে রিসেট করুন (যেমনটি আপনার কোড কনফিগারেশনে সংজ্ঞায়িত করা আছে)।
    2. এজেন্টকে জানাতে যে মানগুলি বাহ্যিকভাবে পরিবর্তিত হয়েছে (ব্যবহারকারীর অনুরোধে নয়, রিসেটের মাধ্যমে), রেজিস্ট্রি পরিষেবাতে UpdateSettings কল করুন।

পশ্চাৎ সামঞ্জস্য এবং স্কিমা বিবর্তন

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

সামঞ্জস্যপূর্ণ পরিবর্তন

একটি ব্যবহারকারী-নিয়ন্ত্রণযোগ্য পরিষেবা তার সেটিংস স্কিমাতে শুধুমাত্র সামঞ্জস্যপূর্ণ পরিবর্তন আনবে। এই পরিবর্তনগুলো নিশ্চিত করে যে পুরোনো ক্লায়েন্টগুলো আপডেট ছাড়াই সঠিকভাবে কাজ চালিয়ে যাবে:

  • একটি যুক্তিসঙ্গত ডিফল্ট মান সহ একটি নতুন, ঐচ্ছিক সেটিং যোগ করুন:

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

অসামঞ্জস্যপূর্ণ পরিবর্তন

নিম্নলিখিত পরিবর্তনগুলি গুরুতর ত্রুটি হিসেবে বিবেচিত এবং নিষিদ্ধ, কারণ এগুলি অবিলম্বে পুরোনো গ্রাহকদের ঝুঁকি বাড়িয়ে তোলে:

  • বিদ্যমান একটি সেটিং মুছে ফেলুন।

  • বিদ্যমান কোনো সেটিংয়ের অর্থ, একক বা ডেটা টাইপ পরিবর্তন করুন (উদাহরণস্বরূপ, সেলসিয়াসে তাপমাত্রা নির্দেশকারী একটি পূর্ণসংখ্যা থেকে প্যাসকেলে চাপ নির্দেশকারী একটি ফ্লোটে পরিবর্তন করা)।

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

প্রয়োজনীয় ব্রেকিং পরিবর্তনগুলি পরিচালনা করুন

যদি কোনো ব্রেকিং চেঞ্জ (breaking change) প্রয়োজন হয়, তবে সার্ভিসটি বিদ্যমান সেটিং পরিবর্তন করবে না । সামঞ্জস্যতা বজায় রেখে এই পরিবর্তনটি পরিচালনা করার পদ্ধতিটি মূলত ব্যবহারকারী-নিয়ন্ত্রণযোগ্য সার্ভিস লজিকের মধ্যেই থাকে:

  1. পছন্দসই নতুন সংজ্ঞা, কী, বা ইউনিট দিয়ে একটি নতুন সেটিং তৈরি করুন।
  2. সামঞ্জস্যতা রক্ষার জন্য বিদ্যমান সেটিংটি রেজিস্টার করে অপ্রচলিত করুন। নতুন ক্লায়েন্ট তৈরি করার সময় এই নতুন সেটিংটি ব্যবহার করুন।
  3. নতুন ক্লায়েন্টদের ব্যবহারকারী-নিয়ন্ত্রণযোগ্য সার্ভিসের বিজনেস লজিকের মধ্যে কম্প্যাটিবিলিটি লজিক প্রয়োগ করার পরামর্শ দিন।

সার্ভিসটির RequestSettingsChange ইমপ্লিমেন্টেশনকে অবশ্যই নিশ্চিত করতে হবে যে, একটি সেটিং-এর পরিবর্তন তার ডেপ্রিকেটেড প্রতিরূপে প্রতিফলিত হয় এবং প্রতিরূপের পরিবর্তন সেটিংটিতেও প্রতিফলিত হয়।

সামঞ্জস্য যুক্তির উদাহরণ:

  1. একটি পরিষেবা পুরোনো TEMPERATURE_C (সেলসিয়াস) সেটিংটি বাতিল করে TEMPERATURE_K (কেলভিন) চালু করেছে।

  2. যখন এজেন্ট নতুন সেটিং আপডেট করার জন্য অনুরোধ পাঠায়:

    • পরিষেবাটি TEMPERATURE_K (উদাহরণস্বরূপ, 295.15 K)-এর জন্য একটি অনুরোধ গ্রহণ করে।

    • সার্ভিসটির লজিক এটিকে সেলসিয়াসে (২২°C) রূপান্তর করে এবং পুরোনো ক্লায়েন্টদের জন্য সামঞ্জস্য বজায় রাখতে অভ্যন্তরীণভাবে উভয় মান আপডেট ও সংরক্ষণ করে।

  3. যখন এজেন্ট একটি লিগ্যাসি ক্লায়েন্ট থেকে অপ্রচলিত সেটিংয়ের জন্য অনুরোধ পাঠায়:

    • পরিষেবাটি TEMPERATURE_C (উদাহরণস্বরূপ, 24°C) এর জন্য একটি অনুরোধ গ্রহণ করে।
    • পরিষেবাটি এটিকে কেলভিনে (২৯৭.১৫ K) রূপান্তর করে এবং অভ্যন্তরীণভাবে উভয় মান আপডেট ও সংরক্ষণ করে।

এই দ্বৈত-লিখন কৌশলটি নিশ্চিত করে যে সমস্ত ক্লায়েন্ট, তাদের রিলিজ সময়সূচী নির্বিশেষে, সামঞ্জস্যপূর্ণ এবং সঠিক ডেটা পড়ে, যার ফলে বাহ্যিক রিলিজের অমিলের কারণে সৃষ্ট সমস্যা এড়ানো যায়।

একজন ক্লায়েন্টকে বাস্তবায়ন করুন

ইউজার প্রেফারেন্সেস এজেন্টের সাথে ইন্টারঅ্যাক্ট করে এমন একটি ক্লায়েন্ট (যেমন, একটি HMI) বাস্তবায়ন করতে:

  1. নির্দিষ্ট ইউজার প্রেফারেন্সেস ইন্টারফেসের সাথে ইন্টারঅ্যাক্ট করার জন্য আপনার ক্লায়েন্ট সার্ভিস বান্ডেল সংজ্ঞায়িত করুন। আপনার VSIDL ফাইলে:

    • সার্ভার হিসেবে, সেটিংস পরিবর্তনের বিষয়ে আপনার ক্লায়েন্টকে রিয়েল-টাইম নোটিফিকেশন পাঠানোর জন্য এজেন্টকে সক্ষম করতে com.sdv.google.user_preferences.view.ChangeNotifier প্রয়োগ করুন।
    • ক্লায়েন্ট হিসেবে, সেটিংস পরিবর্তনের অনুরোধ জানাতে এবং আপডেটের জন্য সাবস্ক্রাইব করতে com.sdv.google.user_preferences.UserPreferencesManagementService ব্যবহার করুন।
    • ক্লায়েন্ট হিসেবে, ব্যবহারকারীর প্রোফাইল পরিচালনা করতে (যেমন, তৈরি করা, নির্বাচন করা, মুছে ফেলা, ফ্যাক্টরি রিসেট করা) com.sdv.google.user_preferences.UserPreferencesAdminService ব্যবহার করুন।

    নিম্নলিখিত উদাহরণটি একজন ক্লায়েন্টের জন্য একটি service_bundle.vsidl ফাইল দেখাচ্ছে:

    service_bundle {
        name: "MyHmiClient"
        server {
            service: "com.sdv.google.user_preferences.view.ChangeNotifier"
        }
        client {
            service: "com.sdv.google.user_preferences.UserPreferencesManagementService"
        }
        client {
            service: "com.sdv.google.user_preferences.UserPreferencesAdminService"
        }
    }
    

    সেই অনুযায়ী অনুমোদন নীতিমালা যোগ করুন। ব্যবহারকারীর পছন্দ নির্ধারণকারী এজেন্টের যোগাযোগের অনুমতি দেওয়ার জন্য, নির্দিষ্ট সার্ভারগুলোর জন্য একটি ক্লায়েন্ট তৈরি করুন। উদাহরণস্বরূপ:

    server {
        service: "com.sdv.google.user_preferences.view.ChangeNotifier"
        allow_all_channels: true
    }
    client {
        service: "com.sdv.google.user_preferences.UserPreferencesManagementService"
        allow_all_channels: true
    }
    client {
        service: "com.sdv.google.user_preferences.UserPreferencesAdminService"
        allow_all_channels: true
    }
    
  2. আপনি UserPreferencesManagementService এ অনুরোধের সেটিংস পরিবর্তন করতে পারেন:

    1. UserPreferencesManagementService এর সাথে সংযোগ করুন।
    2. SettingsGroupId এবং কাঙ্ক্ষিত সেটিংস উল্লেখ করে RequestSettingsChangeRequest এর একটি ইনস্ট্যান্স তৈরি করুন।
    3. ঐচ্ছিক। ChangePersistencePolicy কে PERSISTENT_CHANGE (ডিফল্ট) অথবা NON_PERSISTENT_CHANGE এ সেট করুন।
    4. RequestSettingsChange() কল করুন।

    নিম্নলিখিত উদাহরণটি ধারণাগত রাস্ট-এ লেখা:

    management_client.RequestSettingsChange(&RequestSettingsChangeRequest {
        settings_group_id: Some(SettingsGroupId {
            service_fqin: hvac_service_fqin.to_string(),
            name: "HVAC".to_string(),
            ..Default::default()
        }).into(),
        settings: vec![Setting {
            key: "TEMPERATURE".to_string(),
            value: Some(Value::Int64(24)),
            ..Default::default()
        }],
        change_persistence_policy: ChangePersistencePolicy::PERSISTENT_CHANGE.into(),
        ..Default::default()
    }).await?;
    
  3. user_preferences_management_service.proto এবং change_notifier.proto ব্যবহার করে সেটিংস পরিবর্তনের জন্য সাবস্ক্রাইব করুন:

    1. আপনার সার্ভিস বান্ডেলের মধ্যে ChangeNotifier ইন্টারফেস থেকে OnSettingsChange RPC-টি প্রয়োগ করুন। কোনো পরিবর্তন ঘটলে ইউজার প্রেফারেন্সেস এজেন্ট এই মেথডটি কল করে।
    2. UserPreferencesManagementService এর সাথে সংযোগ করুন।
    3. আপনি যে SettingsGroupId নিরীক্ষণ করতে চান তা উল্লেখ করে একটি SubscribeToSettingsChangeAndGetSettingsRequest তৈরি করুন।
    4. সেটিংসের অবস্থা ফেরত দিতে এবং পরবর্তীতে আপনার OnSettingsChange ইমপ্লিমেন্টেশনের মাধ্যমে আপডেট পাঠাতে, SubscribeToSettingsChangeAndGetSettings() কল করুন।

    ChangeNotifier ইন্টারফেসটি বাস্তবায়নের নিম্নলিখিত উদাহরণটি ধারণাগত রাস্ট ভাষায় লেখা:

    #[async_trait]
    impl ChangeNotifier for MyHmiServiceImpl {
        async fn OnSettingsChange(
            &self,
            _caller_id: ServiceFqin,
            request: &OnSettingsChangeRequest,
        ) -> SdvResult<OnSettingsChangeResponse> {
            // Process the active_settings, pending_changes, and persisted_settings
            // Update your UI or internal state accordingly.
            info!("Received settings change for group: {}", request.settings_group_id.name);
            // ...
            Ok(OnSettingsChangeResponse::new())
        }
    }
    

    সাবস্ক্রাইব করার নিম্নলিখিত উদাহরণটি ধারণাগত রাস্ট ভাষায় লেখা:

    management_client.SubscribeToSettingsChangeAndGetSettings(&SubscribeToSettingsChangeAndGetSettingsRequest {
        settings_group_id: Some(SettingsGroupId {
            service_fqin: hvac_service_fqin.to_string(),
            name: "HVAC".to_string(),
            ..Default::default()
        }).into(),
        ..Default::default()
    }).await?;
    
  4. ঐচ্ছিক: যেসব ক্লায়েন্ট ব্যবহারকারীর প্রোফাইল পরিচালনা করে (উদাহরণস্বরূপ, একটি ডেডিকেটেড সেটিংস অ্যাপ), তারা অ্যাডমিন সার্ভিসের সাথে ইন্টারঅ্যাক্ট করার জন্য user_preferences_admin_service.proto ব্যবহার করতে পারে:

    1. UserPreferencesAdminService এর সাথে সংযোগ করুন।
    2. ব্যবহারকারীর প্রোফাইল পরিচালনা করতে CreateUser , SelectUser , DeleteUser , FactoryReset , এবং ListUsers এর মতো RPC ব্যবহার করুন।

    ব্যবহারকারী তৈরির নিম্নলিখিত উদাহরণটি ধারণাগত রাস্ট ভাষায় লেখা:

    admin_service_client.CreateUser(&CreateUserRequest {
        user: Some(User {
            id: 1,
            flags: UserFlags::DRIVER.value(),
            ..Default::default()
        }).into(),
        ..Default::default()
    }).await?;
    
  5. user_preferences_admin_service.proto এর মাধ্যমে অ্যাডমিন সার্ভিস থেকে উপলব্ধ সেটিংস এবং ব্যবহারকারীদের খুঁজুন:

    1. UserPreferencesAdminServiceListUsers() কল করে সকল নিবন্ধিত ব্যবহারকারীর একটি তালিকা পান।
    2. UserPreferencesAdminServiceGetUserSettings(user_id) কল করে কোনো নির্দিষ্ট ব্যবহারকারীর সেটিংস পাওয়া যায়।

    ব্যবহারকারীদের তালিকা তৈরি এবং সেটিংস পাওয়ার নিম্নলিখিত উদাহরণটি ধারণাগত রাস্ট ভাষায় লেখা:

    // List all users
    let list_users_response = admin_service_client.ListUsers(&ListUsersRequest::new()).await?;
    info!("Available users: {:?}", list_users_response.users);
    
    // Get settings for a specific user (for example, user with ID 1)
    if let Some(user_id) = list_users_response.users.first().map(|u| u.id) {
        let get_settings_response = admin_service_client.GetUserSettings(&GetUserSettingsRequest {
            user_id,
            ..Default::default()
        }).await?;
        info!("Settings for user {}: {:?}", user_id, get_settings_response.groups);
    }
    

প্রবাহের সারাংশ

  1. ক্লায়েন্ট এজেন্টের ব্যবস্থাপনা ও প্রশাসনিক পরিষেবা শুরু করে এবং তাতে সংযুক্ত হয়।
  2. ক্লায়েন্ট সেটিংস গ্রুপগুলি খুঁজে বের করে সেগুলিতে সাবস্ক্রাইব করে এবং প্রাথমিক অবস্থা প্রদর্শন করে।
  3. ক্লায়েন্ট এজেন্টের কাছে একটি RequestSettingsChange পাঠায়।
  4. এজেন্ট ক্লায়েন্টের কাছে আপডেট করা সেটিংস এবং অবস্থা সহ একটি OnSettingsChange নোটিফিকেশন পাঠায়।

একটি সম্পূর্ণ কার্যকরী উদাহরণের জন্য, @samples/user_preferences/v1/ -এ থাকা HMIService টি দেখুন।

এজেন্ট বাস্তবায়ন করুন

একটি অর্কেস্ট্রেটর-চালিত সার্ভিস বান্ডেল ব্যবহারকারীর পছন্দসমূহ এজেন্টটি বাস্তবায়ন করে। সুবিধার জন্য, একটি রেফারেন্স বাস্তবায়ন প্রদান করা হয়েছে।

এছাড়াও, এজেন্টের জন্য এই নমুনা সার্ভিস বান্ডেল user_preferences_sample.vsidl ফাইলটি প্রদান করা হয়েছে:

package: "com.sdv.oem.user_preferences"

service_bundle {
    name: "UserPreferencesServiceBundle"
    server {
        service: "com.sdv.google.user_preferences.UserPreferencesAdminService"
    }
    server {
        service: "com.sdv.google.user_preferences.UserPreferencesManagementService"
    }
    server {
        service: "com.sdv.google.user_preferences.UserPreferencesRegistryService"
    }
    client {
        service: "com.sdv.google.user_preferences.view.ChangeNotifier"
    }
    client {
        service: "com.sdv.google.user_preferences.user_controllable.UserControllableService"
    }
}

বাস্তবায়নটি জেনারেট করা মিডলওয়্যার ব্যবহার করতে পারে এবং এটি একটি rust_ffi_shared এ কম্পাইল হওয়া উচিত, যা ইউজার প্রেফারেন্সেস এজেন্ট বাস্তবায়নকারী সার্ভিস বান্ডেল দ্বারা রেফারেন্সকৃত হয়:

sdv_service_bundle_metadata {
  # This name must match the agent's Bundle Name
  name: "UserPreferencesServiceBundle"
  version_number: 1
  version_name: "1"

  native_library_path: "lib64/<USER-PREFERENCES-FFI-LIB>.so"

  orchestration_config_path: "etc/user_preferences_service_bundle/<USER-PREFERENCES-ORCHESTRATION>.textproto"

  authorization_policy_path: "etc/user_preferences_service_bundle/permissions.textproto"
}

ক্লায়েন্টের অনুমোদন নীতি .textproto ফাইলটির জন্য প্রয়োজনীয় অনুমতিগুলো প্রয়োজন:

client {
    service: "com.sdv.google.user_preferences.UserPreferencesManagementService"
    allow_all_channels: true
}

client {
    service: "com.sdv.google.user_preferences.UserPreferencesRegistryService"
    allow_all_channels: true
}

client {
    service: "com.sdv.google.user_preferences.UserPreferencesAdminService"
    allow_all_channels: true
}

পরিশিষ্ট: মূল ধারণা

এই অংশে কিছু গুরুত্বপূর্ণ ধারণা বর্ণনা করা হয়েছে।

ব্যবহারকারীরা

প্রতিটি যানবাহন ব্যবহারকারী ( User শ্রেণী) একটি অ্যাকাউন্ট তৈরি করতে পারেন যেখানে তারা তাদের পছন্দগুলি সংরক্ষণ করতে পারবেন। ব্যবহারকারীর পছন্দগুলি শুধুমাত্র যানবাহন চালকদের জন্য অ্যাকাউন্ট সমর্থন করে। অতিথি চালকরা অস্থায়ী অ্যাকাউন্ট তৈরি করতে পারেন যা একবার ব্যবহারের পর স্বয়ংক্রিয়ভাবে মুছে যায়।

message User {
  // Required.
  // A unique ID for the user.
  int32 id = 1;

  // Bit flags that define properties of user. Integer values have to be powers of 2 as they are used as
  // a bit mask.
  enum UserFlags {
    // Due to Protobuff requirement to have the first enum option set to 0,
    // Assign 0 to an unused flag
    UNSET = 0x0;
    // Marks the user as vehicle driver
    DRIVER = 0x01;
    // Ephemeral users have non-persistent state, once another user is selected
    // the profile is deleted automatically
    EPHEMERAL = 0x02;
  }

  // Required.
  // Bitmask for the user flags defined above
  int32 flags = 2;
}

সেটিংস গ্রুপ

সেটিংস গ্রুপ ( SettingsGroup ক্লাস) সম্পর্কিত সেটিংসগুলোকে সংগঠিত ও পরিচালনা করে। গাড়ির ভেতরের প্রতিটি কনফিগারযোগ্য উপাদান তার সেটিংসগুলোকে গ্রুপ হিসেবে সংজ্ঞায়িত করে, যা কী-ভ্যালু পেয়ার হিসেবে উপস্থাপিত সেটিংসের একটি তালিকা নিয়ে গঠিত। উদাহরণস্বরূপ, ইলেকট্রিক সিটযুক্ত গাড়িগুলো ড্রাইভারের সিটের জন্য একটি এবং সামনের যাত্রীর জন্য আরেকটি সেটিং গ্রুপ সংজ্ঞায়িত করতে পারে, যেখানে উভয় গ্রুপেই একই নামের সেটিংস থাকে।

message SettingsGroup {
  // Required.
  // The identifier for this group.
  SettingsGroupId id = 1;

  // Required.
  // The version number of schema used by this setting group.
  string version = 2;

  // Required.
  // The list of settings within the setting group.
  repeated Setting settings = 3;
}

সেটিংস

সেটিং মেসেজ ( Setting ক্লাস) হলো SettingsGroup অন্তর্গত একটি একক সেটিং। এই মেসেজটিতে একটি কী (key) থাকে, যা হলো সেটিংটির নাম, এবং একটি ভ্যালু (value) থাকে, যা বিভিন্ন ধরনের যেকোনো একটি হতে পারে।

এই উদাহরণটি দেখায় কিভাবে একটি সেটিং একটি কী এবং একটি ভ্যালু দিয়ে উপস্থাপন করা হয়:

// A key value pair representing a setting within a UserControllableService SettingsGroup.
message Setting {
  // Required.
  // A name that uniquely identifies a setting within a SettingsGroup.
  string key = 1;

  // Required.
  // New value of the setting.
  oneof value {
    bool bool = 2;
    float float = 3;
    int32 int32 = 4;
    int64 int64 = 5;
    bytes blob = 6;
    int32 enum = 7;
  }
}

সেটিং সংজ্ঞা

সেটিং ডেফিনিশন ( SettingDefinition ক্লাস) একটি সেটিংস গ্রুপের অন্তর্গত স্বতন্ত্র সেটিংসের জন্য টেমপ্লেট হিসেবে কাজ করে। এগুলি সেটিংটির মৌলিক বৈশিষ্ট্যগুলি নির্দিষ্ট করে, যেমন সেটিংটি সকল ব্যবহারকারীর জন্য শেয়ার করা হবে, প্রতিটি ব্যবহারকারীর জন্য নির্দিষ্ট হবে, নাকি বাহ্যিকভাবে পরিচালিত হবে (পাসথ্রু)।

গুরুত্বপূর্ণভাবে, সেটিং ডেফিনিশনগুলো সেটিংটির মানের উপর যেকোনো সীমাবদ্ধতাও নির্ধারণ করে, যেমন সর্বনিম্ন ও সর্বোচ্চ মান, অনুমোদিত বৃদ্ধি, বা বিকল্পের একটি সীমিত সেট। এই সীমাবদ্ধতাগুলো প্রতিটি সেটিং-এর জন্য ডেটার অখণ্ডতা এবং সামঞ্জস্য নিশ্চিত করে।

// The definition of a setting, along with its properties such as type and constraints
message SettingDefinition {
  // Required.
  SettingKind kind = 1;

  // Required.
  SettingWithConstraints setting_with_constraints = 2;
}

enum SettingKind {
  // A setting which is applied for all vehicle users.
  SHARED = 0;
  // Store the value of the setting for each vehicle user separately.
  PER_USER = 1;
  // UserControllableService is fully responsible for the storage of PASSTHROUGH setting.
  // User Preferences only notifies UserControllableService when the value is explicitly set by
  // user. User Preferences does not attempt to request changes based on user change or service
  // registration.
  PASSTHROUGH = 2;
};

message SettingWithConstraints {
  // Required
  Setting setting = 1;

  // Required.
  // Defines restrictions on the setting's value
  oneof constraints {
    FloatConstraints float_constraints = 2;
    Int32Constraints int32_constraints = 3;
    Int64Constraints int64_constraints = 4;
    EnumConstraints enum_constraints = 5;
  }
}

message Int32Constraints {
  // The minimum value that a setting can have.
  optional int32 min_value = 1;
  // The maximum value that a setting can have.
  optional int32 max_value = 2;
  // The step by which a setting's value can be increased or decreased.
  optional int32 step = 3;
}

message Int64Constraints {
  // The minimum value that a setting can have.
  optional int64 min_value = 1;
  // The maximum value that a setting can have.
  optional int64 max_value = 2;
  // The step by which a setting's value can be increased or decreased.
  optional int64 step = 3;
}

message FloatConstraints {
  // The minimum value that a setting can have.
  optional float min_value = 1;
  // The maximum value that a setting can have.
  optional float max_value = 2;
  // The step by which a setting's value can be increased or decreased.
  optional float step = 3;
}

message EnumConstraints {
  // Required.
  // List of unique values sorted in ascending order.
  repeated int32 possible_values = 1;
}

যখন কোনো ব্যবহারকারী একটি সেটিং আপডেট করেন, তখন ঘটনাগুলোর একটি উদাহরণমূলক ক্রম।

এই উদাহরণটি সেই ঘটনাক্রম তুলে ধরে যা ঘটে যখন একজন ব্যবহারকারী অ্যান্ড্রয়েড অটোমোটিভ ওএস (AAOS)-এর ইন-ভেহিকেল ইনফোটেইনমেন্ট (IVI) ব্যবহার করে কোনো সেটিং আপডেট করেন:

ব্যবহারকারী যখন সেটিং পরিবর্তন করে তখন ইভেন্ট

চিত্র ১. ব্যবহারকারী কোনো সেটিং পরিবর্তন করলে ঘটা ঘটনাসমূহ।

গাড়ি চালু করার সময়কার ঘটনাক্রমের একটি উদাহরণ।

এই উদাহরণটি দেখায় যে, একটি যানবাহন চালু হওয়ার সময় SDV ইউজার প্রেফারেন্সেস কীভাবে একজন ব্যবহারকারীর পছন্দের সেটিংস প্রয়োগ করে:

গাড়ি চালু হওয়ার সময়কার ঘটনা

চিত্র ২. যানবাহন চালু হওয়ার সময়কার ঘটনাসমূহ।