सॉफ़्टवेयर से तय होने वाले वाहन (एसडीवी) प्लैटफ़ॉर्म पर कॉन्फ़िगरेशन और कैलिब्रेशन सेवा (कॉनकैल) उपलब्ध होती है. यह सेवा, वाहन की खास बातों, देश के नियमों, और ग्राहक के ऑर्डर की गई सुविधाओं के हिसाब से एसडीवी सेवाओं को कॉन्फ़िगर करने की सुविधाएं देती है. यह सेवा, SDV प्लैटफ़ॉर्म का एक बुनियादी बिल्डिंग ब्लॉक है. इसकी मदद से, OEM एक ही सेवा कोड को कई वाहनों में फिर से इस्तेमाल कर सकते हैं. इसके लिए, उन्हें वाहनों को कॉन्फ़िगर करना होगा. साथ ही, कई सोर्स से फिर से कॉन्फ़िगर करने की सुविधा चालू करनी होगी. उदाहरण के लिए, फ़ैक्ट्री में, सर्विस सेंटर में, और क्लाउड से.
SDV प्लैटफ़ॉर्म, किसी खास वाहन पर सेवा बंडल के कॉन्फ़िगरेशन और कैलिब्रेशन के लिए, सेवा से जुड़े एपीआई उपलब्ध कराता है. इस इंटरफ़ेस का इस्तेमाल करके, ओईएम ये काम कर सकते हैं: ओईएम के हिसाब से कॉन्फ़िगरेशन लागू करना और कैलिब्रेशन लॉजिक लागू करना.
कॉन्फ़िगरेशन और कैलिब्रेशन सेवा में ये प्रोसेस शामिल हैं:
कॉन्फ़िगरेशन, जिसमें वाहन की बुनियादी प्रॉपर्टी और व्यवहार तय करना शामिल है. यह कई बातों पर निर्भर कर सकता है, जैसे कि वाहन की जगह, उपयोगकर्ता के ऑर्डर किए गए विकल्प या देश के कानून. यह तय करता है कि कॉम्पोनेंट कैसे इंटरैक्ट करते हैं. साथ ही, यह सॉफ़्टवेयर की उन सेटिंग के बारे में बताता है जो वाहन के सभी फ़ंक्शन पर असर डालती हैं. जैसे, सॉफ़्टवेयर के वैरिएंट, नेटवर्क कनेक्शन, और शुरुआती ऑपरेशनल पैरामीटर.
कैलिब्रेशन, जो सिस्टम के पैरामीटर को पहले से कॉन्फ़िगर की गई रेंज में फ़ाइन-ट्यून करता है. उदाहरण के लिए, कैलिब्रेशन से सेंसर और ऐक्चुएटर की सटीकता को अडजस्ट किया जाता है. साथ ही, उत्सर्जन को कंट्रोल करने के लिए इंजन की परफ़ॉर्मेंस को ऑप्टिमाइज़ किया जाता है. इसके अलावा, ड्राइविंग की क्षमता और सुरक्षा सिस्टम के जवाबों को बेहतर बनाया जाता है. कॉन्फ़िगरेशन से, वाहन के काम करने का बुनियादी फ़्रेमवर्क सेट होता है. वहीं, कैलिब्रेशन से उस फ़्रेमवर्क के हिसाब से वाहन के काम करने के तरीके को ऑप्टिमाइज़ किया जाता है. ये दोनों ही चीज़ें ज़रूरी हैं. इनसे यह पक्का किया जा सकता है कि वाहन, उत्सर्जन से जुड़े नियमों का पालन करते हैं, बेहतर परफ़ॉर्म करते हैं, और सुरक्षित हैं. साथ ही, समय के साथ होने वाले घिसाव की भरपाई भी की जा सकती है.
एसडीवी के लिए स्टैंडर्ड ConCal API उपलब्ध कराकर, हम एसडीवी सेवा बंडलों को लागू करने की प्रोसेस को आसान बनाते हैं. इससे अलग-अलग ओईएम के वाहनों पर कॉन्फ़िगरेशन और कैलिब्रेशन की सुविधाओं को फिर से लागू करने की ज़रूरत नहीं पड़ती.
वास्तुकला
हर सेवा बंडल के पास एक या उससे ज़्यादा कॉन्फ़िगरेशन आर्टफ़ैक्ट हो सकते हैं.
कॉन्फ़िगरेशन आर्टफ़ैक्ट
कॉन्फ़िगरेशन आर्टफ़ैक्ट (कॉन्फ़िगरेशन) में एक या उससे ज़्यादा कॉन्फ़िगरेशन पैरामीटर और उनकी वैल्यू शामिल होती हैं. कॉन्फ़िगरेशन, सेवा के हिसाब से protobuf मैसेज होता है. इसके फ़ील्ड में नेस्ट किए गए protobuf मैसेज (स्ट्रक्चर), मैप, ऐरे, int, फ़्लोट, bool, बाइट या स्ट्रिंग पैरामीटर शामिल हो सकते हैं.
// 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.
प्रतिबंध:
- इंस्टेंस का नाम किसी अक्षर से शुरू होना चाहिए.
- सभी वर्ण, लोअरकेस अल्फ़ान्यूमेरिक या हाइफ़न होने चाहिए.
- नाम में हाइफ़न, एक से ज़्यादा बार लगातार नहीं दिखने चाहिए.
- कॉन्फ़िगरेशन के नाम के आखिर में हाइफ़न नहीं होना चाहिए.
- कॉन्फ़िगरेशन का नाम 48 वर्णों से ज़्यादा का नहीं होना चाहिए.
- एक ही सेवा बंडल के लिए, एक ही वीएम पर कॉन्फ़िगरेशन के नाम अलग-अलग होने चाहिए.
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;
}
बूट के समय कॉन्फ़िगरेशन के मालिक को सिर्फ़ कॉन्फ़िगरेशन का स्कीमा और इसकी डिफ़ॉल्ट वैल्यू पता होती हैं. किसी मौजूदा वाहन के लिए, सेवा-बंडल के व्यवहार को पसंद के मुताबिक बनाने के लिए, सेवा-बंडल के मालिक को अपने स्कीमा के साथ-साथ डिफ़ॉल्ट कॉन्फ़िगरेशन रजिस्टर करना होगा.
पहली इमेज. डिफ़ॉल्ट कॉन्फ़िगरेशन का रजिस्ट्रेशन और पसंद के मुताबिक बनाए गए कॉन्फ़िगरेशन को वापस पाना.
इससे ओईएम, सेवा बंडलों को एक बार लागू कर सकते हैं और उन्हें कई वाहनों पर लागू कर सकते हैं.
डिप्लॉयमेंट
ConCal, SDV प्लैटफ़ॉर्म पर एक या उससे ज़्यादा सर्वर इंस्टेंस बनाए रख सकता है. सेवा बंडलों को सबसे नज़दीकी ConCal सर्वर का पता लगाना चाहिए और उसका इस्तेमाल करना चाहिए. उदाहरण के लिए, अगर हर ईसीयू के लिए एक ConCal डिप्लॉय किया गया है, तो सेवा बंडल को उसी ईसीयू पर चल रहे ConCal इंस्टेंस का ऐक्सेस मिलना चाहिए. इससे सेवा बंडल, कॉन्फ़िगरेशन को समय पर वापस पा सकता है. अगर ConCal इंस्टेंस में अनुरोध किया गया कॉन्फ़िगरेशन नहीं है (क्योंकि यह किसी दूसरे ConCal की ज़िम्मेदारी के दायरे में आता है), तो संपर्क किया गया ConCal सर्वर, इसे मालिकाना हक वाले ConCal इंस्टेंस से अनुरोध करता है और इसे सेवा बंडल पर रीडायरेक्ट करता है.
कॉन्फ़िगरेशन को पसंद के मुताबिक बनाना
एसडीवी का एक मुख्य फ़ायदा यह है कि एक ही सॉफ़्टवेयर को अलग-अलग वाहनों में इस्तेमाल किया जा सकता है. सॉफ़्टवेयर को एक बार बनाया जाता है. इसके बाद, इसका इस्तेमाल कई वाहनों में किया जाता है. साथ ही, हम वाहन की खासियतों के हिसाब से सॉफ़्टवेयर के व्यवहार में बदलाव कर सकते हैं. ConCal का मुख्य मकसद यही है. यह कॉन्फ़िगरेशन ओवरराइड की मदद से, वाहन की प्रॉपर्टी के आधार पर सेवा के कॉन्फ़िगरेशन का हिसाब लगाता है.
ConfigOverride एक प्रोटोबफ़ मैसेज है. इसमें बताया गया है कि किसी वाहन के हिसाब से कॉन्फ़िगरेशन को कैसे अडजस्ट किया जाए. इसमें एक ओवरराइड आईडी होता है, जिसे इसे उपलब्ध कराने वाली इकाई खास तौर पर तय करती है. साथ ही, इसमें एक कॉन्फ़िगरेशन आइडेंटिफ़ायर और ConfigOverrideKeyValuePair की सूची होती है. ConfigOverride सिर्फ़ अपडेट की प्रोसेस के दौरान दिया जा सकता है. साथ ही, इसे सिर्फ़ उन सेवाओं से दिया जा सकता है जिन्हें अनुमति मिली है. ओईएम, इन सेवाओं को मॉडल करता है. दोनों स्ट्रक्चर के लिए, प्रोटोबफ़ की परिभाषाएं यहां दी गई हैं.
// 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, फ़्लोट, bool, बाइट) को नई वैल्यू असाइन करना या मैप, सूचियां, स्ट्रक्चर या पूरे कॉन्फ़िगरेशन जैसे जटिल फ़ील्ड को फिर से लिखना.
वैल्यू हटाना या साफ़ करना: यह कार्रवाई सभी टाइप के लिए उपलब्ध है. जैसे, मैसेज, दोहराए गए फ़ील्ड, मैप, सिंगुलर फ़ील्ड, और कॉन्फ़िगरेशन. इस ऑपरेशन को पूरे फ़ील्ड या मैसेज पर किया जा सकता है. इसका मतलब है कि मैप में मौजूद कुछ कुंजियों और दोहराए गए फ़ील्ड में मौजूद अलग-अलग एलिमेंट को हटाने की सुविधा उपलब्ध नहीं है.
मैप में कोई नई वैल्यू जोड़ें.
मैप में मौजूद किसी कुंजी की वैल्यू को फिर से लिखें. अगर कुंजी मौजूद नहीं है, तो इस कार्रवाई को मैप में नई वैल्यू जोड़ने के तौर पर भी किया जा सकता है.
ConCal का इस्तेमाल करके, सेवा का बंडल कॉन्फ़िगर करना
इस चैप्टर में, ऐसे सर्विस बंडल को डेवलप करने का तरीका बताया गया है जो रनटाइम पर अपना कॉन्फ़िगरेशन वापस पाता है. कॉन्फ़िगर किए जा सकने वाले बंडल के हिसाब से, यह पूरी तरह से पता नहीं चलता कि कॉन्फ़िगरेशन, फ़ैक्ट्री की डिफ़ॉल्ट सेटिंग है या ConCal ओवरराइडिंग और कैलिब्रेशन प्रोसेस का इस्तेमाल करके किया गया बाद का बदलाव है.
दस्तावेज़ में इस्तेमाल किया गया सैंपल, system/software_defined_vehicle/samples/concal/src/concal_client पर देखा जा सकता है.
ज़्यादा जानकारी के लिए, सेवा बंडल तैयार करना लेख पढ़ें.
यह एलान करना कि सेवा बंडल के पास किस तरह का कॉन्फ़िगरेशन है
सेवा बंडल, उस कॉन्फ़िगरेशन का टाइप तय करता है जिसे वह वापस पाता है. इससे कॉन्फ़िगर किए जा सकने वाले बंडल को, सेव किए गए कॉन्फ़िगरेशन डेटा से अलग से अपडेट किया जा सकता है.
कॉन्फ़िगरेशन टाइप का एलान करने वाली,
.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; }एक ऐसा बिल्ड टारगेट बनाएं जो रनटाइम लाइब्रेरी जनरेट करता हो. इससे कॉन्फ़िगरेशन टाइप को वापस पाने की अनुमति मिलती है.
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 कॉन्फ़िगरेशन रजिस्ट्रेशन और डेटा वापस पाने की सेवा का क्लाइंट है. बंडल के लिए आरपीसी क्लाइंट बाइंडिंग जनरेट करने के लिए, VSIDLC का इस्तेमाल करने की खास जानकारी के लिए, VSIDL और मिडलवेयर की खास जानकारी देखें.
आरपीसी कॉन्फ़िगरेशन को वापस पाने के लिए मिडलवेयर को शुरू करना
रन टाइम पर, ConCal आरपीसी कॉल के लिए ज़रूरी मिडलवेयर कॉम्पोनेंट शुरू करें. इस उदाहरण में, बंडल शुरू होने पर हम एसिंक्रोनस तरीके से शुरू करते हैं.
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में, हम एक tokio रनटाइम बनाते हैं और एक tokio टास्क स्पॉन करते हैं. यह टास्क, बंडल के मुख्य लॉजिक को आगे बढ़ाने से पहलेsetup_register_rpcको कॉल करता है.setup_register_rpcमिडलवेयर आरपीसी बाइंडिंग सेट अप करता है. ध्यान दें कि इस उदाहरण में यह नहीं माना गया है कि ConCal की सुविधा को एजेंट ने लागू किया है: सर्वर, बंडल शुरू होने के बाद ही उपलब्ध हो सकता है. इसलिए, उदाहरण के तौर पर दिए गए कोड में, आरपीसी सर्वर के रजिस्टर होने का इंतज़ार किया जाता है. इसके लिए, Service Discovery API का इस्तेमाल किया जाता है.
कॉन्फ़िगरेशन शुरू करना
कॉन्फ़िगरेशन आर्टफ़ैक्ट को रजिस्टर करें. इसके लिए, 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(®istration_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में टास्क शुरू होता है. इसके बाद, कारोबारी नियम लागू होते हैं औरsample_concal_mainको कॉल किया जाता है. sample_concal_mainकॉन्फ़िगरेशन आर्टफ़ैक्ट को रजिस्टर करके शुरू होता है. लॉजिकregister_configमें शामिल है.- किसी कॉन्फ़िगरेशन को रजिस्टर करने के लिए, बंडल को अपना प्रोटोबफ़ टाइप, आईडी, और डिफ़ॉल्ट वैल्यू तय करनी होगी.
config_fdकॉन्फ़िगरेशन टाइप है. कॉन्फ़िगरेशन टाइप का मालिकाना हक रखने वाला बंडल यह पक्का करता है कि बंडल के लिए ज़रूरी स्कीमा हमेशा वापस पाया जाए. इसमें APEX अपडेट के बाद का स्कीमा भी शामिल है.- इस आईडी का इस्तेमाल, ConCal सर्वर के इंटरनल परसिस्टेंस लॉजिक में आइडेंटिफ़ायर के तौर पर किया जाता है.
- डिफ़ॉल्ट वैल्यू
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(®istration_client, &config_id, &config).await;
let config = get_config(®istration_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फ़ंक्शन, उन्हें पार्स करके कॉन्फ़िगरेशन के अनुमानित टाइप में बदलता है.