بدء استخدام Fleet Engine

تتيح لك واجهة برمجة تطبيقات الرحلات عند الطلب والتسليمات في Fleet Engine إدارة الرحلات وحالة المركبة لتطبيقات الرحلة والطلبات. فهي تعالج المعاملات بين حزمة Driver SDK وحزمة تطوير البرامج (SDK) للمستهلكين والخدمة الخلفية التي يمكنها الاتصال بخدمة Fleet Engine من خلال إجراء استدعاءات gRPC أو REST.

المتطلّبات الأساسية

لإجراء تطوير، احرص على تثبيت حزمة تطوير البرامج (SDK) للسحابة الإلكترونية (gcloud) ومصادقتها على مشروعك.

shell

gcloud auth login

من المفترض أن تظهر لك رسالة نجاح مثل:

You are now logged in as [my-user@example.com].
Your current project is [project-id].  You ...

تأكَّد من أنّه قد تم ضبط واجهات برمجة تطبيقات الرحلات عند الطلب وتسليمات الحلول Fleet Engine بشكل مناسب.

shell

gcloud --project=project-id services enable fleetengine.googleapis.com

إذا نتج عن هذا الأمر خطأ، تحقق مع مشرف المشروع وممثل الدعم في Google للحصول على إمكانية الوصول.

التسجيل

يمكن لفريق Fleet Engine كتابة رسائل سجلّ حول طلبات البيانات من واجهة برمجة التطبيقات التي يتلقّاها في سجلات Google Cloud Platform. راجِع وثائق التسجيل في السحابة الإلكترونية للحصول على نظرة عامة حول كيفية قراءة السجلات وتحليلها.

قد لا يكون التسجيل مفعَّلاً تلقائيًا للمشروعات التي تم إنشاؤها قبل 10 شباط (فبراير) 2022. راجع مستندات التسجيل للحصول على مزيد من التفاصيل.

مكتبات العملاء

وننشر مكتبات العملاء بعدة لغات برمجة شائعة. ستساعد هذه المكتبات في توفير تجربة مطوّرين أفضل مقارنةً بـ REST أو gRPC الأوّلي. للحصول على تعليمات عن كيفية الحصول على مكتبات العملاء لتطبيق الخادم، يُرجى الاطّلاع على مكتبات العميل.

تفترض أمثلة Java في هذه الوثائق الإلمام بـ gRPC.

المصادقة والترخيص

يمكنك ضبط الإمكانات التي يوفّرها مستوى تقدّم الرحلات والطلبات من خلال Google Cloud Console. تتطلّب واجهات برمجة التطبيقات وحِزم تطوير البرامج (SDK) هذه استخدام الرموز المميّزة للويب JSON التي تم توقيعها باستخدام حسابات الخدمة التي تم إنشاؤها من Cloud Console.

إعداد مشروع على السحابة الإلكترونية

لإعداد مشروعك على السحابة الإلكترونية، عليك أولاً إنشاء مشروعك، ثم إنشاء حسابات خدمة.

لإنشاء مشروعك على Google Cloud، اتّبِع الخطوات التالية:

  1. أنشِئ مشروعًا على Google Cloud باستخدام Google Cloud Console.
  2. باستخدام لوحة بيانات الخدمات وواجهات برمجة التطبيقات، يمكنك تفعيل واجهة برمجة تطبيقات الرحلات المحلية والتسليمات.

ترتبط حسابات الخدمة بدور واحد أو أكثر. وتُستخدَم لإنشاء رموز JSON المميّزة للويب التي تمنح مجموعات مختلفة من الأذونات اعتمادًا على الأدوار. ويمكنك عادةً إنشاء حسابات خدمة متعددة للحدّ من احتمالية إساءة الاستخدام، ولكلٍّ منها حد أدنى من مجموعة الأدوار المطلوبة.

يستخدم مستوى تقدّم الرحلة والطلبات الأدوار التالية:

Roleالوصف
مستخدم حزمة SDK لمستهلك Fleet Engine

roles/fleetengine.consumerSdkUser
يمنح الإذن بالبحث عن المركبات واسترداد معلومات عن المركبات والرحلات. ويتم عادةً استخدام الرموز المميّزة التي ينشئها حساب الخدمة مع هذا الدور من الأجهزة الجوّالة التي يوفّرها تطبيق المستهلك لخدمات مشاركة الرحلات أو التوصيل.
مستخدم Fleet Engine Driver SDK

roles/fleetengine.driverSdkUser
يمنح الإذن بتعديل المواقع الجغرافية للمركبات ومساراتها واسترداد معلومات عن المركبات والرحلات. إنّ الرموز المميّزة التي ينشئها حساب خدمة بهذا الدور تُستخدم عادةً من الأجهزة الجوّالة لمشاركة الرحلات أو تطبيق السائقين التسليم.
مشرف Fleet Engine عند الطلب

roles/fleetengine.ondemandAdmin
يمنح الإذن بالقراءة والكتابة لجميع موارد المركبات والرحلات. لا يحتاج المشرفون الذين لديهم هذا الدور إلى استخدام JWT، بل يمكنهم بدلاً من ذلك استخدام بيانات الاعتماد التلقائية للتطبيق. يتم تجاهل مطالبات JWT المخصّصة. ويجب أن يقتصر هذا الدور على البيئات الموثوق بها (الواجهة الخلفية للعميل).
المستخدم المتميّز في خدمة FleetEngine **(متوقّف)**

roles/fleetengine.serviceSuperUser
يمنح الإذن لجميع واجهات برمجة تطبيقات المركبات والرحلات. ويتم عادةً استخدام الرموز المميّزة التي يتم إنشاؤها من خلال حساب خدمة يتولى هذا الدور من خوادم الخلفية. تم إيقاف هذا الدور نهائيًا. يُفضّل استخدام roles/fleetengine.ondemandAdmin بدلاً من ذلك.

على سبيل المثال، يمكنك إنشاء حساب خدمة لكل من الأدوار الثلاثة وتعيين الأدوار الخاصة لكل منها.

gcloud --project=project-id iam service-accounts create fleet-engine-consumer-sdk
gcloud projects add-iam-policy-binding project-id \
       --member=serviceAccount:fleet-engine-consumer-sdk@project-id.iam.gserviceaccount.com \
       --role=roles/fleetengine.consumerSdkUser

gcloud --project=project-id iam service-accounts create fleet-engine-driver-sdk
gcloud projects add-iam-policy-binding project-id \
       --member=serviceAccount:fleet-engine-driver-sdk@project-id.iam.gserviceaccount.com \
       --role=roles/fleetengine.driverSdkUser

gcloud --project=project-id iam service-accounts create fleet-engine-su
gcloud projects add-iam-policy-binding project-id \
       --member=serviceAccount:fleet-engine-su@project-id.iam.gserviceaccount.com \
       --role=roles/fleetengine.serviceSuperUser

تم إنشاء حِزم تطوير البرامج (SDK) الخاصة بكل من السائق والمستهلك استنادًا إلى هذه الأدوار العادية.

يمكنك بدلاً من ذلك إنشاء أدوار مخصَّصة تسمح بتجميع مجموعة عشوائية من الأذونات معًا. ستعرض حزمتا تطوير البرامج (SDK) لبرنامج التشغيل والمستهلك رسائل خطأ عند عدم توفُّر إذن مطلوب. نتيجةً لذلك، ننصحك بشدة باستخدام المجموعة العادية من الأدوار الموضّحة أعلاه وعدم استخدام الأدوار المخصَّصة.

للتيسير عليك، إذا كنت بحاجة إلى إنشاء رموز JWT للعملاء غير الموثوق بهم، ستتيح لهم إضافة مستخدمين إلى دور منشئ الرموز المميزة لحساب الخدمة إنشاء رموز مميزة باستخدام أدوات سطر أوامر gcloud.

gcloud projects add-iam-policy-binding project-id \
       --member=user:my-user@example.com \
       --role=roles/iam.serviceAccountTokenCreator

حيث my-user@example.com هو البريد الإلكتروني المستخدم للمصادقة باستخدام gcloud (gcloud auth list --format='value(account)').

مكتبة مصادقة Fleet Engine

يستخدم Fleet Engine رموز JSON Web Tokens (JWTs) لحظر الوصول إلى واجهات برمجة تطبيقات Fleet Engine. تعمل مكتبة Fleet Engine الجديدة - المتاحة على GitHub ، على تبسيط إنشاء رموز JWT في Fleet Engine وتوقيعها بأمان.

توفر المكتبة الفوائد التالية:

  • تبسيط عملية إنشاء الرموز المميّزة لـ Fleet Engine
  • يتم توفير آليات توقيع الرمز المميّز بخلاف استخدام ملفات بيانات الاعتماد (مثل انتحال هوية حساب خدمة.)
  • تُرفق الرموز المميّزة الموقَّعة للطلبات الصادرة التي يتم إجراؤها من خلال كعب gRPC أو عميل GAPIC.

إنشاء رمز JSON المميّز للويب (JWT) للتفويض

في حال عدم استخدام Fleet Engine Auth Library، يجب إنشاء رموز JSON Web Token (JWTs) مباشرةً داخل قاعدة الرموز لديك. وهذا يتطلب منك أن يكون لديك فهم عميق لـ JWT وكيفية ارتباطها بـ Fleet Engine. ولهذا السبب، ننصح بشدة بالاستفادة من مكتبة مصادقة Fleet Engine.

داخل Fleet Engine، توفّر رموز JSON للويب (JWT) مصادقة قصيرة الأجل، وتضمن إمكانية تعديل الأجهزة للمركبات أو الرحلات أو المهام فقط التي تم التصريح لها بذلك. تحتوي ملفات JWT على عنوان وقسم مطالبة. يحتوي قسم العنوان على معلومات مثل المفتاح الخاص المطلوب استخدامه (الذي يتم الحصول عليه من حسابات الخدمة) وخوارزمية التشفير. ويحتوي قسم المطالبة على معلومات مثل وقت إنشاء الرمز المميّز ووقت بقاء الرمز المميّز والخدمات التي يطلب التطبيق الوصول إليها ومعلومات التفويض الأخرى لتحديد نطاق الوصول إلى البيانات، مثل معرّف المركبة.

يحتوي قسم عنوان JWT على الحقول التالية:

الحقلالوصف
alg الخوارزمية المطلوب استخدامها. `RS256`.
typ تمثّل هذه السمة نوع الرمز المميّز. "JWT".
طفلة رقم تعريف المفتاح الخاص لحساب الخدمة. يمكنك العثور على هذه القيمة في الحقل "private_key_id" في ملف JSON لحساب الخدمة. تأكَّد من استخدام مفتاح من حساب خدمة يتضمّن مستوى الأذونات الصحيح.

يحتوي قسم مطالبات JWT على الحقول التالية:

الحقلالوصف
هوس عنوان البريد الإلكتروني لحساب الخدمة.
sub عنوان البريد الإلكتروني لحساب الخدمة.
Aud SERVICE_NAME لحساب الخدمة الخاص بك، في هذه الحالة https://fleetengine.googleapis.com/
بروتوكول الإنترنت الطابع الزمني الذي انقضى منه الرمز المميّز بالثواني 1 كانون الثاني (يناير) 1970 عند الساعة 00:00:00 حسب التوقيت العالمي المنسّق (UTC) اسمح لمدة 10 دقائق للحصول على انحراف. وإذا كان الطابع الزمني بعيدًا جدًا في الماضي أو في المستقبل، قد يُبلغ الخادم عن خطأ.
exp الطابع الزمني لوقت انتهاء صلاحية الرمز المميّز، والذي يتم تحديده بالثواني المنقضي منذ 1 كانون الثاني (يناير) 1970 الساعة 00:00:00 حسب التوقيت العالمي المنسَّق (UTC). يتعذّر تقديم الطلب إذا كان الطابع الزمني يقع بعد أكثر من ساعة واحدة في المستقبل.
authorization حسب حالة الاستخدام، قد يحتوي على "vehicleid" أو "tripid".

يشير إنشاء رمز JWT المميز إلى التوقيع عليه. للحصول على تعليمات ونماذج التعليمات البرمجية لإنشاء JWT وتوقيعه، اطلع على تفويض حساب الخدمة بدون OAuth. يمكنك بعد ذلك إرفاق رمز مميّز موقَّع باستدعاءات gRPC أو الطرق الأخرى المستخدمة للوصول إلى Fleet Engine.

مطالبات JWT

عند إنشاء حمولة JWT، أضِف مطالبة أخرى في قسم التفويض مع ضبط المفتاح vehicleid أو tripid على قيمة معرّف المركبة أو معرّف الرحلة التي يتم إجراء المكالمة من أجلها.

تستخدم "حزمة تطوير البرامج (SDK) لبرنامج التشغيل" دائمًا المطالبة vehicleid، سواء كانت تعمل في رحلة أو مركبة. تؤكد الواجهة الخلفية لـ Fleet Engine أن المركبة مرتبطة بالرحلة المطلوبة قبل إجراء التعديل.

دائمًا ما تستخدم حزمة تطوير البرامج (SDK) الخاصة بالمستهلك مطالبة واحدة (tripid).

على مقدّم خدمة مشاركة الرحلات أو مقدّم خدمة التوصيل استخدام vehicleid أو tripid مع علامة "*" لمطابقة جميع المركبات والرحلات. تجدر الإشارة إلى أنّ JWT يمكن أن يحتوي على كلا الرمزَين المميّزَين، حتى إذا لم يكن ذلك مطلوبًا، ما قد يؤدي إلى تبسيط عملية توقيع الرمز المميّز.

حالات الاستخدام في JWT

في ما يلي مثال على رمز مميز لخادم الموفّر:

{
  "alg": "RS256",
  "typ": "JWT",
  "kid": "private_key_id_of_provider_service_account"
}
.
{
  "iss": "provider@yourgcpproject.iam.gserviceaccount.com",
  "sub": "provider@yourgcpproject.iam.gserviceaccount.com",
  "aud": "https://fleetengine.googleapis.com/",
  "iat": 1511900000,
  "exp": 1511903600,
  "authorization": {
     "vehicleid": "*",
     "tripid": "*"
   }
}

في ما يلي مثال على رمز مميّز من أجل تطبيق المستهلك:

{
  "alg": "RS256",
  "typ": "JWT",
  "kid": "private_key_id_of_consumer_service_account"
}
.
{
  "iss": "consumer@yourgcpproject.iam.gserviceaccount.com",
  "sub": "consumer@yourgcpproject.iam.gserviceaccount.com",
  "aud": "https://fleetengine.googleapis.com/",
  "iat": 1511900000,
  "exp": 1511903600,
  "authorization": {
     "tripid": "trip_54321"
   }
}

يوضح ما يلي مثالاً على رمز مميز لتطبيق Driver:

{
  "alg": "RS256",
  "typ": "JWT",
  "kid": "private_key_id_of_driver_service_account"
}
.
{
  "iss": "driver@yourgcpproject.iam.gserviceaccount.com",
  "sub": "driver@yourgcpproject.iam.gserviceaccount.com",
  "aud": "https://fleetengine.googleapis.com/",
  "iat": 1511900000,
  "exp": 1511903600,
  "authorization": {
     "vehicleid": "driver_12345"
   }
}
  • بالنسبة إلى الحقل kid في العنوان، حدِّد رقم تعريف المفتاح الخاص لحساب الخدمة. يمكنك العثور على هذه القيمة في الحقل private_key_id ضمن ملف JSON لحساب الخدمة.
  • في الحقلين iss وsub، حدِّد عنوان البريد الإلكتروني لحساب الخدمة. يمكنك العثور على هذه القيمة في الحقل client_email ضمن ملف JSON لحساب الخدمة.
  • بالنسبة إلى الحقل aud، حدِّد https://SERVICE_NAME/.
  • بالنسبة إلى الحقل iat، استخدِم الطابع الزمني عند إنشاء الرمز المميّز، والذي يتم تحديده على أنّه الثواني التي انقضت منذ الساعة 00:00:00 حسب التوقيت العالمي المنسَّق (UTC) في 1 كانون الثاني (يناير) 1970. اسمح لمدة 10 دقائق للحصول على انحراف. وإذا كان الطابع الزمني بعيدًا جدًا في الماضي، أو في المستقبل، قد يبلغ الخادم عن خطأ.
  • بالنسبة إلى الحقل exp، استخدِم الطابع الزمني عند انتهاء صلاحية الرمز المميّز، والذي تم تحديده كثوانيٍ منذ الساعة 00:00:00 حسب التوقيت العالمي المنسَّق (UTC) في 1 كانون الثاني (يناير) 1970. الحد الأقصى المسموح به هو iat + 3600.

عند توقيع ملف JWT لإرساله إلى جهاز جوّال، تأكَّد من استخدام حساب الخدمة لدور برنامج التشغيل أو حزمة تطوير البرامج (SDK) للمستهلك. بخلاف ذلك، سيتمكّن الجهاز الجوّال من تغيير الحالة التي من المفترض ألا تتوفّر فيها.

وبالمثل، عند توقيع JWT لاستخدامه في المكالمات المميزة، تأكَّد من استخدام حساب الخدمة الذي يمتلك دور "المستخدم المميّز". وإلا ستفشل العملية.

إنشاء JWT للاختبار

قد يكون إنشاء الرموز المميّزة من الوحدة الطرفية مفيدًا أثناء الاختبار.

لاتّباع هذه الخطوات، يجب أن يكون لحساب المستخدم دور "منشئ الرموز المميّزة لحساب الخدمة":

gcloud projects add-iam-policy-binding project-id \
       --member=user:my-user@example.com \
       --role=roles/iam.serviceAccountTokenCreator

أنشئ ملفًا جديدًا باسم "unsigned_token.json" يتضمّن المحتوى أدناه. والسمة iat هي الوقت الحالي بعدد الثواني التي تلي الحقبة، والذي يمكن استرجاعه من خلال تشغيل date +%s في الوحدة الطرفية. والسمة exp هي مدة انتهاء الصلاحية بعدد الثواني التي تلي الحقبة التي يمكن احتسابها من خلال إضافة 3600 إلى iat. لا يمكن أن يكون وقت انتهاء الصلاحية أكثر من ساعة واحدة في المستقبل.

{
  "aud": "https://fleetengine.googleapis.com/",
  "iss": "super-user-service-account@project-id.iam.gserviceaccount.com",
  "sub": "super-user-service-account@project-id.iam.gserviceaccount.com",
  "iat": iat,
  "exp": exp,
  "authorization": {
     "vehicleid": "*",
     "tripid": "*"
   }
}

بعد ذلك، شغِّل الأمر gcloud التالي لتوقيع الرمز المميّز نيابةً عن حساب خدمة Super User:

gcloud beta iam service-accounts sign-jwt --iam-account=super-user-service-account@project-id.iam.gserviceaccount.com unsigned_token.json signed_token.jwt

من المفترَض أن يتم الآن تخزين ملف JWT موقَّع بترميز Base64 ضمن الملف signed_token.jwt. الرمز المميز صالح للساعة التالية.

يمكنك الآن اختبار الرمز المميّز من خلال تنفيذ الأمر curl على نقطة نهاية "قائمة المركبات" REST:

curl -X GET "https://fleetengine.googleapis.com/v1/providers/project-id/vehicles" -H "Authorization: Bearer $(cat signed_token.jwt)"

المركبات ودورة حياتها

المركبة هي الكيان الذي يمثل زوجًا من مركبة السائق. وفي الوقت الحالي، لا يمكن تتبّع السائق والمركبة بشكل منفصل. ينشئ موفّر خدمة مشاركة الرحلات أو مقدّم خدمة التوصيل مركبة باستخدام رقم تعريف موفّر الخدمة (يجب أن يكون مطابقًا لرقم تعريف المشروع الخاص بمشروع Google Cloud الذي يحتوي على حساب الخدمة المستخدَم لطلب واجهات برمجة تطبيقات Fleet Engine) ورقم تعريف مركبة يملكها موفّر خدمة مشاركة الرحلات أو شركة التوصيل.

سيتم تلقائيًا حذف أي مركبة لم يتم تحديثها عبر UpdateVehicle بعد مرور سبعة أيام. حدث خطأ عند طلب CreateVehicle باستخدام معرّف الموفّر/معرّف المركبة. يمكن التعامل مع المركبات التي لا يتم تحديثها كثيرًا بطريقتَين، هما: الاتصال برقم "CreateVehicle" بشكل متكرّر مع إظهار رقم تعريف المركبة/رقم تعريف المركبة، وإلغاء الخطأ إذا كانت المركبة متوفرة، أو طلب CreateVehicle بعد رجوع UpdateVehicle مع ظهور الخطأ NOT_FOUND.

إشعارات بشأن الموقع الجغرافي للمركبة

للحصول على أفضل أداء باستخدام Fleet Engine، يمكنك تزويده بمجموعة من المعلومات التي تحتاج إليها حول الموقع الجغرافي للمركبة. استخدِم إحدى الطريقتَين التاليتَين لتقديم هذه التعديلات:

  1. استخدم Driver SDK - Android و iOS -- الخيار الأبسط.
  2. استخدِم رمزًا مخصصًا، وهو مفيد إذا كان يتم ترحيل المواقع الجغرافية من خلال الخلفية أو إذا كنت تستخدم أجهزة أخرى غير Android أو iOS.

أنواع المركبات

تتضمّن كيان المركبة الحقل المطلوب VehicleType، الذي يتضمّن تعداد Category يمكن تحديده على النحو التالي: AUTO أو TAXI أو TRUCK أو TWO_WHEELER أو BICYCLE أو PEDESTRIAN. يمكن استخدام نوع المركبة كمعايير فلتر في SearchVehicles وListVehicles.

ستستخدم جميع مسارات التوجيه للمركبات السمة RouteTravelMode المناسبة إذا تم ضبط الفئة على AUTO أو TWO_WHEELER أو BICYCLE أو PEDESTRIAN. في حال ضبط الفئة على TAXI أو TRUCK، يتم التعامل مع التوجيه بالطريقة نفسها المتّبعة مع وضع AUTO.

سمات المركبات

تتضمّن كيان المركبة حقلاً متكرّرًا للسمة VehicleAttribute. لا يتم تفسير هذه السمات من قبل Fleet Engine. تشمل واجهة برمجة التطبيقات SearchVehicles حقلًا يشترط فيه أنّ السمة Vehicles المطابِقة يجب أن تحتوي على جميع السمات المضمّنة المضبوطة على القيمة المحدّدة.

يُرجى العلم أنّ حقل السمة بالإضافة إلى عدة حقول أخرى متوافقة في رسالة Vehicle، مثل vehicle_type وsupported_trip_types.

نقاط الطريق المتبقية للمركبة

تحتوي كيان المركبة على حقل متكرّر للسمة TripWaypoint (RPC | REST)، باسم waypoints(RPC | REST). يتضمن هذا الحقل نقاط الطريق المتبقية في الرحلات، بالترتيب الذي تصل به المركبة إليها. يقوم Fleet Engine بحساب هذا الحقل حيث يتم تعيين الرحلات للمركبة، ويحدثه عندما تغير الرحلات حالتها. يمكن تحديد نقاط الطريق هذه من خلال الحقل TripId والحقل WaypointType.

زيادة أهلية المركبات للمشاركة في المباريات

في العادة، تكون خدمات مشاركة الرحلات أو مقدّم خدمة التوصيل مسؤولة عن مطابقة طلبات الرحلات مع المركبات. يمكن للخدمة استخدام سمات المركبة لتضمين مركبة في عدد أكبر من عمليات البحث. على سبيل المثال، يمكن للموفر تنفيذ مجموعة لسمات مرتبطة بمستويات المزايا أو الإمكانات التي توفرها السيارة. على سبيل المثال، يمكن أن تكون ثلاثة مستويات عبارة عن مجموعة من السمات ذات القيم المنطقية: is_bronze_level وis_silver_level وis_gold_level. يمكن أن تكون المركبة مؤهلة لثلاثة أنواع. عندما يتلقى Fleet Engine طلبًا برحلة تتطلب إمكانات المستوى الفضي، فإن البحث يتضمن تلك المركبة. ويشمل استخدام السمات بهذه الطريقة المركبات التي تقدّم مجموعة متنوعة من القدرات.

تتوفّر طريقتان لتعديل سمات المركبة: الأولى هي واجهة برمجة تطبيقات UpdateVehicle. عند استخدام واجهة برمجة التطبيقات هذه، يتم ضبط مجموعة "سمات المركبة" بالكامل على القيمة. لا يمكن تعديل سمة واحدة فقط. أما الطريقة الأخرى، فهي UpdateVehicleAttributes API. تتطلّب هذه الطريقة تعديل السمات فقط. سيتمّ ضبط السمات المضمّنة في الطلب على القيمة الجديدة أو إضافتها، ولن يتمّ تغيير السمات غير المحدّدة.

طريقة التنفيذ: إنشاء مركبة

يجب إنشاء كيان "Vehicle" لكل مركبة ليتم تتبّعها في الأسطول.

استخدِم نقطة نهاية CreateVehicle مع CreateVehicleRequest لإنشاء مركبة.

يجب أن يكون provider_id من Vehicle هو رقم تعريف المشروع (مثل المشروع عند الطلب) الخاص بمشروع Google Cloud الذي يحتوي على حسابات الخدمة التي سيتم استخدامها للاتصال بـ Fleet Engine. يُرجى ملاحظة أنّه على الرغم من إمكانية وصول حسابات خدمة متعددة إلى Fleet Engine لموفّر خدمات النقل أو مشاركة الرحلات نفسه، لا يتيح Fleet Engine حاليًا استخدام حسابات الخدمة من عدّة مشاريع على Google Cloud تتيح الوصول إلى Vehicles نفسه.

يمكن إنشاء Vehicle بالحالة OFFLINE أو ONLINE. إذا تم إنشاء ONLINE، قد يتم إرجاعه فورًا استجابةً لطلبات SearchVehicles.

قد يتم تضمين last_location مبدئي في مكالمة CreateVehicle. وعلى الرغم من السماح بذلك، يجب ألا يتم إنشاء Vehicle في الحالة ONLINE بدون last_location.

راجِع أنواع المركبات للحصول على تفاصيل حول حقل نوع المركبة.

راجِع سمات المركبة للحصول على تفاصيل حول حقل السمات.

القيمة التي يعرضها CreateVehicle هي كيان Vehicle الذي تم إنشاؤه.

مثال

shell

curl -X POST \
  "https://fleetengine.googleapis.com/v1/providers/project-id/vehicles?vehicleId=vid-8241890" \
  -H "Authorization: Bearer $JWT" \
  -H "Content-Type: application/json" \
  --data-binary @- << EOM
{
    "vehicleState": "OFFLINE",
    "supportedTripTypes": ["EXCLUSIVE"],
    "maximumCapacity": 4,
    "vehicleType": {"category": "AUTO"},
    "attributes": [{"key": "on_trip", "value": "false"}]
}
EOM

يُرجى الاطّلاع على المرجع providers.vehicles.create.

Java

static final String PROJECT_ID = "project-id";

VehicleServiceBlockingStub vehicleService =
    VehicleService.newBlockingStub(channel);

String parent = "providers/" + PROJECT_ID;
Vehicle vehicle = Vehicle.newBuilder()
    .setVehicleState(VehicleState.OFFLINE)  // Initial state
    .addSupportedTripTypes(TripType.EXCLUSIVE)
    .setMaximumCapacity(4)
    .setVehicleType(VehicleType.newBuilder().setCategory(VehicleType.Category.AUTO))
    .addAttributes(VehicleAttribute.newBuilder()
        .setKey("on_trip").setValue("false"))  // Opaque to the Fleet Engine
    // Add .setBackToBackEnabled(true) to make this vehicle eligible for trip
    // matching while even if it is on a trip.  By default this is disabled.
    .build();

CreateVehicleRequest createVehicleRequest =
    CreateVehicleRequest.newBuilder()  // no need for the header
        .setParent(parent)
        .setVehicleId("vid-8241890")  // Vehicle ID assigned by Rideshare or Delivery Provider
        .setVehicle(vehicle)  // Initial state
        .build();

// In this case, the Vehicle is being created in the OFFLINE state and
// no initial position is being provided.  When the Driver App checks
// in with the Rideshare or Delivery Provider, the state can be set to ONLINE and
// the Driver App will update the Vehicle Location.

try {
  Vehicle createdVehicle =
      vehicleService.createVehicle(createVehicleRequest);
} catch (StatusRuntimeException e) {
  Status s = e.getStatus();
  switch (s.getCode()) {
    case ALREADY_EXISTS:
      break;
    case PERMISSION_DENIED:
      break;
  }
  return;
}
// If no Exception, Vehicle created successfully.

سجلّات Google Cloud Platform لإنشاء المركبات

تكتب واجهة برمجة تطبيقات Fleet Engine إدخالاً في السجلّ عبر سجلات Google Cloud Platform عند تلقّي طلب بنقطة نهاية CreateVehicle. ويتضمّن إدخال السجلّ معلومات حول القيم في طلب CreateVehicle. إذا نجحت المكالمة، سيتم تضمين معلومات عن Vehicle الذي تم إرجاعه.

shell

gcloud --project=project-id logging read --freshness=1h '
  jsonPayload.request.vehicleId="vid-8241890"
  jsonPayload.@type="type.googleapis.com/maps.fleetengine.v1.CreateVehicleLog"
'

يجب طباعة سجلّ مشابه لما يلي:

---
insertId: c2cf4d3a180251c1bdb892137c14f022
jsonPayload:
  '@type': type.googleapis.com/maps.fleetengine.v1.CreateVehicleLog
  request:
    vehicle:
      attributes:
      - key: on_trip
        value: 'false'
      maximumCapacity: 4
      state: VEHICLE_STATE_OFFLINE
      supportedTrips:
      - EXCLUSIVE_TRIP
      vehicleType:
        vehicleCategory: AUTO
    vehicleId: vid-8241890
  response:
    attributes:
    - key: on_trip
      value: 'false'
    availableCapacity: 4
    currentRouteSegmentHandle: AdSiwAwCO9gZ7Pw5UZZimOXOo41cJTjg/r3SuwVPQmuuaV0sU3+3UCY+z53Cl9i6mWHLoCKbBt9Vsj5PMRgOJ8zX
    maximumCapacity: 4
    name: providers/project-id/vehicles/vid-8241890
    state: VEHICLE_STATE_OFFLINE
    supportedTrips:
    - EXCLUSIVE_TRIP
    vehicleType:
      vehicleCategory: AUTO
labels:
  vehicle_id: vid-8241890
logName: projects/project-id/logs/fleetengine.googleapis.com%2Fcreate_vehicle
receiveTimestamp: '2021-09-22T03:25:16.361159871Z'
resource:
  labels:
    location: global
    resource_container: projects/project-id
  type: fleetengine.googleapis.com/Fleet
timestamp: '2021-09-22T03:25:15.724998Z'

إشعارات Cloud Pub/Sub حول إنشاء مركبة

تنشر واجهة برمجة تطبيقات Fleet Engine إشعارًا عبر Cloud Pub/Sub عند إنشاء مركبة جديدة. لتلقّي هذه الإشعارات، يُرجى اتّباع التعليمات هنا.

طريقة التنفيذ: تعديل الموقع الجغرافي للمركبة

إذا لم تكن تستخدم "حزمة تطوير البرامج (SDK) للسائق" لتعديل الموقع الجغرافي للمركبة، يمكنك إجراء اتصال مباشر بخدمة Fleet Engine مع الموقع الجغرافي للمركبة. بالنسبة إلى أي مركبة نشطة، يتوقع Fleet Engine تحديث الموقع مرة واحدة على الأقل كل دقيقة ومرة واحدة كل 5 ثوانٍ على الأكثر. لا تتطلّب هذه التحديثات سوى امتيازات مستخدم Fleet Engine Driver SDK.

مثال

shell

curl -X PUT \
  "https://fleetengine.googleapis.com/v1/providers/project-id/vehicles/vid-8241890?updateMask=last_location" \
  -H "Authorization: Bearer $JWT" \
  -H "Content-Type: application/json" \
  --data-binary @- << EOM
{
    "supplementalLocation": {"latitude": 12.1, "longitude": 14.5},
    "supplementalLocationTime": "$(date -u --iso-8601=seconds)",
    "supplementalLocationSensor": "CUSTOMER_SUPPLIED_LOCATION",
    "supplementalLocationAccuracy": 15
}
EOM

يُرجى الاطّلاع على المرجع providers.vehicles.update.

Java

static final String PROJECT_ID = "project-id";
static final String VEHICLE_ID = "vid-8241890";

VehicleServiceBlockingStub vehicleService = VehicleService.newBlockingStub(channel);

String vehicleName = "providers/" + PROJECT_ID + "/vehicles/" + VEHICLE_ID;
Vehicle updatedVehicle = Vehicle.newBuilder()
    .setLastLocation(VehicleLocation.newBuilder()
        .setSupplementalLocation(LatLng.newBuilder()
            .setLatitude(37.3382)
            .setLongitude(121.8863))
        .setSupplementalLocationTime(now())
        .setSupplementalLocationSensor(LocationSensor.CUSTOMER_SUPPLIED_LOCATION)
        .setSupplementalLocationAccuracy(DoubleValue.of(15.0)))  // Optional)
    .build();

UpdateVehicleRequest updateVehicleRequest = UpdateVehicleRequest.newBuilder()
    .setName(vehicleName)
    .setVehicle(updatedVehicle)
    .setUpdateMask(FieldMask.newBuilder()
        .addPaths("last_location"))
    .build();

try {
  Vehicle updatedVehicle =
      vehicleService.updateVehicle(updateVehicleRequest);
} catch (StatusRuntimeException e) {
  Status s = e.getStatus();
  switch (s.getCode()) {
    case NOT_FOUND:
      // Most implementations will call CreateVehicle in this case
      break;
    case PERMISSION_DENIED:
      break;
  }
  return;
}
// If no Exception, Vehicle updated successfully.

طريقة التنفيذ: تعديل حقول المركبات الأخرى

ويتم إجراء تعديلات على السمات الأخرى لحالة المركبة بوتيرة أقل مقارنةً بتحديثات الموضع. تتطلّب التعديلات على السمات الأخرى غير last_location امتيازات "المستخدم المميّز" في مجموعة المحرّكات.

يشتمل UpdateVehicleRequest على update_mask للإشارة إلى الحقول التي يجب تعديلها. ويكون سلوك الحقل كما في وثائق Protobuf بالنسبة لأقنعة الحقل.

كما هو موضّح في سمات المركبة، يتطلب تعديل حقل attributes كتابة جميع السمات للاحتفاظ بها. لا يمكن تعديل قيمة زوج واحد من المفتاح/القيمة فقط في استدعاء UpdateVehicle. لتعديل قيم سمات معيّنة، يمكن استخدام واجهة برمجة التطبيقات UpdateVehicleAttributes.

مثال

يتيح هذا المثال تفعيل السمة back_to_back.

shell

curl -X PUT \
  "https://fleetengine.googleapis.com/v1/providers/project-id/vehicles/vid-8241890?updateMask=vehicle_state,attributes,back_to_back_enabled" \
  -H "Authorization: Bearer $JWT" \
  -H "Content-Type: application/json" \
  --data-binary @- << EOM
{
    "vehicleState": "ONLINE",
    "attributes": [
      {"key": "on_trip", "value": "true"},
      {"key": "cash_only", "value": "false"}
    ],
    "backToBackEnabled": true
}
EOM

يُرجى الاطّلاع على المرجع providers.vehicles.update.

Java

static final String PROJECT_ID = "project-id";
static final String VEHICLE_ID = "vid-8241890";

VehicleServiceBlockingStub vehicleService = VehicleService.newBlockingStub(channel);

String vehicleName = "providers/" + PROJECT_ID + "/vehicles/" + VEHICLE_ID;
Vehicle updatedVehicle = Vehicle.newBuilder()
    .setVehicleState(VehicleState.ONLINE)
    .addAllAttributes(ImmutableList.of(
        VehicleAttribute.newBuilder().setKey("on_trip").setValue("true").build(),
        VehicleAttribute.newBuilder().setKey("cash_only").setValue("false").build()))
    .setBackToBackEnabled(true)
    .build();

UpdateVehicleRequest updateVehicleRequest = UpdateVehicleRequest.newBuilder()
    .setName(vehicleName)
    .setVehicle(updatedVehicle)
    .setUpdateMask(FieldMask.newBuilder()
        .addPaths("vehicle_state")
        .addPaths("attributes")
        .addPaths("back_to_back_enabled"))
    .build();

// Attributes and vehicle state are being updated, so both are
// included in the field mask.  Note that of on_trip were
// not being updated, but rather cash_only was being changed,
// the desired value of "on_trip" would still need to be written
// as the attributes are completely replaced in an update operation.

try {
  Vehicle updatedVehicle =
      vehicleService.updateVehicle(updateVehicleRequest);
} catch (StatusRuntimeException e) {
  Status s = e.getStatus();
  switch (s.getCode()) {
    case NOT_FOUND:
      // Most implementations will call CreateVehicle in this case
      break;
    case PERMISSION_DENIED:
      break;
  }
  return;
}
// If no Exception, Vehicle updated successfully.

سجلّات Google Cloud Platform لتحديثات المركبات

تكتب واجهة برمجة تطبيقات Fleet Engine إدخالاً في السجلّ عبر سجلات Google Cloud Platform عند تلقّي طلب بنقطة نهاية UpdateVehicle. ويتضمّن إدخال السجلّ معلومات حول القيم في طلب UpdateVehicle. إذا نجحت المكالمة، سيتم تضمين معلومات عن Vehicle الذي تم إرجاعه.

shell

gcloud --project=project-id logging read --freshness=1h '
  jsonPayload.request.vehicleId="vid-8241890"
  jsonPayload.@type="type.googleapis.com/maps.fleetengine.v1.UpdateVehicleLog"
'

إشعارات Cloud Pub/Sub حول تحديثات المركبات

تنشر واجهة برمجة تطبيقات Fleet Engine إشعارًا عبر Cloud Pub/Sub عند تحديث مركبة حالية. لتلقّي هذه الإشعارات، يُرجى اتّباع التعليمات هنا.

طريقة التنفيذ: البحث عن مركبات

يدعم Fleet Engine البحث عن المركبات. تتيح لك واجهة برمجة التطبيقات SearchVehicles العثور على السائقين القريبين الذين يكونون أكثر ملاءمة لمهمة مثل خدمة سيارة أو طلب توصيل. تعرض واجهة برمجة التطبيقات SearchVehicles قائمة مرتبة للسائقين الذين يطابقون سمات المهام مع سمات المركبات في أسطولك. لمزيد من المعلومات، يُرجى الاطّلاع على العثور على السائقين القريبين.

مثال

عند البحث عن مركبات متاحة، يستبعد Fleet Engine المركبات التي في الرحلات النشطة تلقائيًا. ويجب أن تتضمن خدمات "مشاركة الرحلة" أو "مقدِّم خدمات التوصيل" بشكل صريح في طلبات البحث. يوضح المثال التالي كيفية تضمين تلك المركبات في البحث عن مركبات تطابق رحلة من Grand Indonesia East Center إلى مركز بالاي سيدانغ جاكرتا للمؤتمرات.

shell

عليك أولاً تعديل موقع المركبة الذي أنشأناه في الخطوات السابقة لتكون مؤهلة. في العالم الحقيقي، سيتم ذلك من خلال حزمة تطوير البرامج (SDK) لبرنامج التشغيل التي تعمل على جهاز Android أو iOS في السيارة.

curl -X PUT \
  "https://fleetengine.googleapis.com/v1/providers/project-id/vehicles/vid-8241890?updateMask=last_location,attributes" \
  -H "Authorization: Bearer $JWT" \
  -H "Content-Type: application/json" \
  --data-binary @- << EOM
{
  "lastLocation": {
    "updateTime": "$( date -u +"%Y-%m-%dT%H:%M:%SZ" )",
    "location": {
      "latitude": "-6.195139",
      "longitude": "106.820826"
    }
  },
  "attributes": [{"key": "on_trip", "value": "false"}]
}
EOM

ومن المفترض أن يسفر إجراء البحث عن تلك المركبة على الأقل.

curl -X POST \
  "https://fleetengine.googleapis.com/v1/providers/project-id/vehicles:search" \
  -H "Authorization: Bearer $JWT" \
  -H "Content-Type: application/json" \
  --data-binary @- << EOM
{
  "pickupPoint": {
    "point": {"latitude": "-6.195139", "longitude": "106.820826"}
  },
  "dropoffPoint": {
    "point": {"latitude": "-6.1275", "longitude": "106.6537"}
  },
  "pickupRadiusMeters": 2000,
  "count": 10,
  "minimumCapacity": 2,
  "tripTypes": ["EXCLUSIVE"],
  "vehicleTypes": [{"category": "AUTO"}],
  "filter": "attributes.on_trip=\"false\"",
  "orderBy": "PICKUP_POINT_ETA",
  "includeBackToBack": true
}
EOM

يُرجى الاطّلاع على المرجع providers.vehicles.search.

Java

static final String PROJECT_ID = "project-id";

VehicleServiceBlockingStub vehicleService = VehicleService.newBlockingStub(channel);

String parent = "providers/" + PROJECT_ID;
SearchVehiclesRequest searchVehiclesRequest = SearchVehiclesRequest.newBuilder()
    .setParent(parent)
    .setPickupPoint( // Grand Indonesia East Mall
        TerminalLocation.newBuilder().setPoint(
            LatLng.newBuilder().setLatitude(-6.195139).setLongitude(106.820826)))
    .setDropoffPoint( // Balai Sidang Jakarta Convention Center
        TerminalLocation.newBuilder().setPoint(
            LatLng.newBuilder().setLatitude(-6.213796).setLongitude(106.807195)))
    .setPickupRadiusMeters(2000)
    .setCount(10)
    .setMinimumCapacity(2)
    .addTripTypes(TripType.EXCLUSIVE)
    .addVehicleTypes(VehicleType.newBuilder().setCategory(VehicleType.Category.AUTO))
    .setFilter("attributes.on_trip=\"false\"")
    .setOrderBy(VehicleMatchOrder.PICKUP_POINT_ETA)
    .setIncludeBackToBack(true) // Fleet Engine includes vehicles that are en route.
    .build();

// Error handling
// If matches are returned and the authentication passed, the request completed
// successfully

try {
  SearchVehiclesResponse searchVehiclesResponse =
      vehicleService.searchVehicles(searchVehiclesRequest);

  // Search results: Each vehicle match contains a vehicle entity and information
  // about the distance and ETA to the pickup point and dropoff point.
  List<VehicleMatch> vehicleMatches = searchVehiclesResponse.getMatchesList();
} catch (StatusRuntimeException e) {
  Status s = e.getStatus();
  switch (s.getCode()) {
    case NOT_FOUND:
      break;
    case PERMISSION_DENIED:
      break;
  }
  return;
}

طلب بحث عن فلترة المركبات

يتيح SearchVehicles وListVehicles الفلترة حسب سمات المركبة باستخدام طلب بحث للفلترة. للتعرّف على بنية طلب البحث للفلتر، يمكنك الاطّلاع على AIP-160 للحصول على أمثلة.

يُرجى العلم أنّ طلبات البحث عن الفلاتر تتيح فقط الفلترة حسب سمات المركبات، ولا يمكن استخدامها في الحقول الأخرى. يعمل طلب بحث الفلتر كعبارة AND مع قيود أخرى، مثل minimum_capacity أو vehicle_types في SearchVehiclesRequest.

طريقة التنفيذ: إدراج المركبات

تم تحسين "SearchVehicles" للعثور على عدد صغير من المركبات بترتيب سريع جدًا، ويُستخدَم بشكل أساسي للعثور على السائقين القريبين الأكثر ملاءمةً لمهمة معيّنة. ومع ذلك، تريد أحيانًا العثور على جميع المركبات التي تفي ببعض المعايير حتى إذا كان التنقل خلال النتائج ضروريًا. تم تصميم ListVehicles لحالة الاستخدام هذه.

تتيح لك واجهة برمجة التطبيقات ListVehicles العثور على جميع المركبات التي تستوفي بعض خيارات الطلبات المحدّدة. تعرض واجهة برمجة التطبيقات ListVehicles قائمة مركبات مقسّمة على صفحات في المشروع تتطابق مع بعض المتطلبات.

لفلترة سمات المركبات، يُرجى الرجوع إلى طلب البحث عن "فلترة المركبات".

مثال

يؤدي هذا المثال إلى إجراء فلترة على vehicle_type والسمات باستخدام سلسلة filter.

shell

curl -X POST \
  "https://fleetengine.googleapis.com/v1/providers/project-id/vehicles:list" \
  -H "Authorization: Bearer $JWT" \
  -H "Content-Type: application/json" \
  --data-binary @- << EOM
{
  "vehicleTypes": [{"category": "AUTO"}],
  "filter": "attributes.on_trip=\"false\"",
}
EOM

يُرجى الاطّلاع على المرجع providers.vehicles.list.

Java

static final String PROJECT_ID = "project-id";

VehicleServiceBlockingStub vehicleService = VehicleService.newBlockingStub(channel);

String parent = "providers/" + PROJECT_ID;
ListVehiclesRequest listVehiclesRequest = ListVehiclesRequest.newBuilder()
    .setParent(parent)
    .addTripTypes(TripType.EXCLUSIVE)
    .addVehicleTypes(VehicleType.newBuilder().setCategory(VehicleType.Category.AUTO))
    .setFilter("attributes.on_trip=\"false\"")
    .setIncludeBackToBack(true) // Fleet Engine includes vehicles that are en route.
    .build();

// Error handling
// If matches are returned and the authentication passed, the request completed
// successfully

try {
  ListVehiclesResponse listVehiclesResponse =
      vehicleService.listVehicles(listVehiclesRequest);
} catch (StatusRuntimeException e) {
  Status s = e.getStatus();
  switch (s.getCode()) {
    case NOT_FOUND:
      break;
    case PERMISSION_DENIED:
      break;
  }
  return;
}

الرحلات ومراحل نشاطها

تشابه واجهة برمجة تطبيقات الرحلة ورحلة النشاط مع واجهة برمجة تطبيقات المركبات ومراحل النشاط. يكون مزود خدمة مشاركة الرحلات مسؤولًا عن إنشاء الرحلات باستخدام واجهات Fleet Engine. يوفّر Fleet Engine كلاً من خدمة استدعاء إجراء عن بُعد (RPC) TripService وموارد REST، وهي provider.trips. تتيح هذه الواجهات إنشاء كيانات "الرحلة" وتقديم طلبات المعلومات ووظيفة البحث وإمكانية التحديث.

يحتوي Trip على حقل حالة لتتبُّع مستوى التقدّم خلال مراحل النشاط. تنتقل القيم من NEW إلى COMPLETE بالإضافة إلى CANCELED وUNKNOWN_TRIP_STATUS. راجِع trip_status للاطّلاع على استدعاء الإجراءات عن بُعد (RPC) أو TripStatus for REST.

  • NEW
  • ENROUTE_TO_PICKUP
  • ARRIVED_AT_PICKUP
  • ENROUTE_TO_INTERMEDIATE_DESTINATION
  • ARRIVED_AT_INTERMEDIATE_DESTINATION
  • ENROUTE_TO_DROPOFF
  • COMPLETE

يمكن لخدمتك تعديل الرحلة إلى CANCELED من أي من هذه الحالات. عندما تنشئ خدمتك رحلة، يضبط المحرّك الحالة على "NEW". وتُعد السمة vehicle_id اختيارية. كما هو الحال مع المركبات، تحذف الخدمات الرحلات تلقائيًا بعد سبعة أيام بدون تحديث. إذا حاولت خدمتك إنشاء رحلة باستخدام معرّف متوفّر، سيتم عرض خطأ. تُعتبر الرحلة "نشطة" إذا كانت في حالة أخرى غير COMPLETE أو CANCELED. هذا التمييز مهم في الحقل active_trips في كيان المركبة وSearchTripsRequest.

لا يمكن لخدمتك تغيير vehicle_id المُخصصة لرحلة إلا عندما تكون الرحلة نشطة. على سبيل المثال، يمكنك فعل ذلك عندما يلغي أحد السائقين رحلة أثناء تواجده على الطريق ويعيد تخصيص الرحلة إلى مركبة مختلفة.

تُعد الحالة مهمة عند تنفيذ دعم الرحلة التدريجية. ويتيح هذا الدعم لمقدم الخدمة تعيين رحلة جديدة إلى مركبة عندما تكون هذه المركبة في رحلة نشطة. ويشبه الرمز لإنشاء "رحلة انتقالية" رمز رحلة واحدة ويستخدم معرّف المركبة نفسه. يضيف Fleet Engine منشأ ووجهة الرحلة الجديدة إلى نقاط طريق المركبة. للحصول على مزيد من المعلومات حول الرحلات المتتالية، يُرجى الاطّلاع على إنشاء رحلات متعددة النقاط.

نقاط الطريق المتبقية للرحلة

يحتوي كيان الرحلة على حقل متكرّر من TripWaypoint (RPC | REST)، يُسمى remainingWaypoints(RPC | REST). يتضمّن هذا الحقل جميع نقاط الطريق التي يجب أن تقطعها المركبة بالترتيب قبل نقطة التسليم النهائية لهذه الرحلة. وهو يحتسب من نقاط الطريق المتبقية للمركبة. في حالات الاستخدام "تعاقب" و"مشاركة رحلة السيارة"، تحتوي هذه القائمة على نقاط طريق من الرحلات الأخرى التي سيتم اجتيازها قبل هذه الرحلة، ولكنها تستبعد أي نقاط طريق بعد هذه الرحلة. ويمكن تحديد النقطة الوسيطة في القائمة من خلال TripId وWaypointType.

العلاقة بين حالة الرحلة ونقاط الطريق المتبقية للمركبة

سيتم تعديل نقاط المسار المتبقية للمركبة (RPC | REST) عندما يتلقّى Fleet Engine طلب تغيير حالة الرحلة. ستتم إزالة نقطة الطريق السابقة من قائمة نقاط الطريق المتبقية للمركبة عند تغيير tripStatus(RPC | REST) من حالة أخرى إلى ENROUTE_TO_XXX. وهذا يعني أنّه عند تغيير حالة الرحلة من ENROUTE_TO_PICKUP إلى ARRIVED_AT_PICKUP، ستبقى نقطة الركوب الخاصة بالرحلة ضمن قائمة نقاط الطريق المتبقية للمركبة، ولكن عندما يتم تغيير حالة الرحلة إلى ENROUTE_TO_INTERMEDIATE_Destination أو ENROUTE_TO_DROPOFF، ستتم إزالتها من نقطة الركوب المتبقية.

وكذلك هو الحال بالنسبة إلى ARRIVED_AT_INTERMEDIATE_Destination وENROUTE_TO_INTERMDEDIATE_Destination. عند "ARRIVED_AT_INTERMEDIATE_ "، لن تتم إزالة الوجهة الوسيطة الحالية من قائمة نقاط الطريق الباقية للمركبة إلى أن تُبلغ المركبة عن أنّها تقود مركبتها إلى نقطة الطريق التالية.

عند تغيير حالة الرحلة إلى COMPLETED، لن تظهر أي نقاط مسار من هذه الرحلة في قائمة النقاط المتبقية للمركبة.

طريقة التنفيذ: إنشاء رحلة

يجب إنشاء كيان Trip ليتم تتبُّع كل طلب رحلة ومطابقته مع "المركبات" في الأسطول. استخدِم نقطة نهاية CreateTrip مع CreateTripRequest لإنشاء رحلة.

السمات التالية مطلوبة لإنشاء رحلة:

  • parent: سلسلة تتضمّن رقم تعريف موفّر الخدمة الذي تم إنشاؤه عند إنشاء مشروع Google Cloud.
  • trip_id - سلسلة أنشأها "مقدِّم خدمة مشاركة الرحلات".
  • trip - حاوية تتضمّن بيانات وصفية أساسية تصف الرحلة
    • trip_type - تعداد يوضّح ما إذا كانت الرحلة قد تضم ركابًا آخرين من مصدر ووجهة مختلفَين في المركبة نفسها (SHARED) أو من طرف واحد فقط (EXCLUSIVE)
    • pickup_point - TerminalLocation الذي يمثل نقطة انطلاق الرحلة راجِع مرجع استدعاء إجراء عن بُعد (RPC) أو مرجع RPC

عند إنشاء رحلة، يمكنك توفير number_of_passengers وdropoff_point وvehicle_id. على الرغم من أنّ هذه الحقول غير مطلوبة، سيتم الاحتفاظ بها في حال تقديمها. ويتم تجاهل جميع حقول "الرحلة" الأخرى. على سبيل المثال، تبدأ كل الرحلات بـ trip_status من NEW حتى إذا تجاوزت trip_status من CANCELED في طلب الإنشاء.

مثال

ينشئ المثال التالي رحلة إلى جراند إندونيسيا إيست مول. إنّ الرحلة حصرية لراكبَين. يجب أن يكون provider_id من Trip هو نفسه رقم تعريف المشروع. في المثال، أنشأ موفّر مشاركة الرحلات مشروع Google Cloud، project-id. يجب أن يحتوي هذا المشروع على حسابات الخدمة المستخدمة لاستدعاء Fleet Engine. حالة الرحلة هي "NEW".

في وقت لاحق، بعد تطابق الخدمة مع معلومات الرحلة إلى مركبة، يمكن للخدمة الاتصال بـ UpdateTrip وتغيير vehicle_id عندما تكون الرحلة مخصّصة لمركبة.

shell

curl -X POST \
  "https://fleetengine.googleapis.com/v1/providers/project-id/trips?tripId=tid-1f97" \
  -H "Authorization: Bearer $JWT" \
  -H "Content-Type: application/json" \
  --data-binary @- << EOM
{
  "tripType": "EXCLUSIVE",
  "numberOfPassengers": 2,
  "pickupPoint": {
    "point": {"latitude": "-6.195139", "longitude": "106.820826"}
  },
  "dropoffPoint": {
    "point": {"latitude": "-6.1275", "longitude": "106.6537"}
  }
}
EOM

يُرجى الاطّلاع على المرجع providers.trips.create.

Java

static final String PROJECT_ID = "project-id";

TripServiceBlockingStub tripService = TripService.newBlockingStub(channel);

String parent = "providers/" + PROJECT_ID;
Trip trip = Trip.newBuilder()
    .setTripType(TripType.EXCLUSIVE) // Use TripType.SHARED for carpooling
    .setPickupPoint(                 // Grand Indonesia East Mall
        TerminalLocation.newBuilder().setPoint(
            LatLng.newBuilder().setLatitude(-6.195139).setLongitude(106.820826)))
    // Provide the number of passengers if available.
    .setNumberOfPassengers(2)
    // Provide the drop-off point if available.
    .setDropoffPoint(
        TerminalLocation.newBuilder().setPoint(
            LatLng.newBuilder().setLatitude(-6.1275).setLongitude(106.6537)))
    .build();

CreateTripRequest createTripRequest =
    CreateTripRequest.newBuilder()  // no need for the header
        .setParent(parent)
        .setTripId("tid-1f97")  // Trip ID assigned by the Provider
        .setTrip(trip)              // Initial state
        .build();

// Error handling
// If Fleet Engine does not have trip with that id and the credentials of the
// requestor pass, the service creates the trip successfully.

try {
  Trip createdTrip =
      tripService.createTrip(createTripRequest);
} catch (StatusRuntimeException e) {
  Status s = e.getStatus();
  switch (s.getCode()) {
    case ALREADY_EXISTS:
      break;
    case PERMISSION_DENIED:
      break;
  }
  return;
}

سجلّات Google Cloud Platform لإنشاء الرحلات

تكتب واجهة برمجة تطبيقات Fleet Engine إدخالاً في السجلّ باستخدام سجلّات Google Cloud Platform عند تلقّي طلب بنقطة نهاية CreateTrip. ويتضمّن إدخال السجلّ معلومات حول القيم في طلب CreateTrip. إذا نجحت المكالمة، سيتم تضمين معلومات عن Trip الذي تم إرجاعه.

طريقة التنفيذ: تعديل رحلة

يحتوي كيان "الرحلة" على حقول تُفعّل التتبُّع حسب الخدمة ولإعداد تقارير عن تقدُّم الرحلة من خلال "حزمة تطوير البرامج (SDK) لبرنامج التشغيل" و"حزمة تطوير البرامج (SDK) الخاصة بالمستهلك". لتعديل السمات، استخدِم رسالة UpdateTripRequest. يؤدي ذلك إلى تعديل حقول "الرحلة" وفقًا لـ field_mask في الطلب. راجِع UpdateTripRequest.

"مقدِّم خدمة مشاركة الرحلات" مسؤول عن تعديل السمات التالية:

  • حالة الرحلة.
  • رقم تعريف المركبة سواء في وقت الإنشاء أو بعد مطابقة المركبة مع رحلة.
  • التغييرات في استلام الطلب أو التسليم أو نقاط الطريق

يحدِّث Fleet Engine الحقول التالية تلقائيًا عند استخدام ميزة مشاركة الرحلة من خلال حزمة تطوير البرامج (SDK) لبرنامج التشغيل أو حزمة تطوير البرامج (SDK) للمستهلك:

  • المسارات
  • الوقت المُقدّر للوصول
  • المسافة المتبقية
  • الموقع الجغرافي للمركبة
  • نقاط الطريق المتبقية

راجِع القسم Tripفي RPC أو Resource.Trip في REST.

سجلّات Google Cloud Platform للاطّلاع على "آخر الأخبار"

تكتب واجهة برمجة تطبيقات Fleet Engine إدخالاً في السجلّ باستخدام سجلّات Google Cloud Platform عند تلقّي طلب بنقطة نهاية UpdateTrip. ويتضمّن إدخال السجلّ معلومات حول القيم في طلب UpdateTrip. إذا نجحت المكالمة، فستتضمّن أيضًا معلومات حول Trip الذي تم إرجاعه.

طريقة التنفيذ: البحث عن الرحلات

يدعم Fleet Engine البحث عن الرحلات. كما أشرنا سابقًا، يتم حذف أي رحلة تلقائيًا بعد سبعة أيام، لذا لا يعرض SearchTrips سجلاً كاملاً لجميع الرحلات.

على الرغم من أنّ SearchTrips هي واجهة برمجة تطبيقات مرنة، تراعي القائمة أدناه حالتَي استخدام.

  • تحديد الرحلات النشطة للمركبة: يمكن لموفّر المحتوى تحديد رحلات مركبة نشطة حاليًا. في SearchTripsRequest، يتم ضبط vehicle_id على المركبة قيد النظر، ويجب ضبط active_trips_only على true.

  • تسوية حالة موفّر الخدمة مع حالة محرّك الأسطول: يمكن لموفّر الخدمة استخدام SearchTrips لضمان تطابق حالة "الرحلة" مع "محرك Fleet Engine". وهذا مهم بشكل خاص لحالة TripStatus. إذا لم يتم ضبط حالة الرحلة المخصّصة لمركبة بشكل صحيح على COMPLETE أو CANCELED، لا تشمل السمة SearchVehicles المركبة.

لاستخدام SearchTrips بهذه الطريقة، اترك vehicle_id فارغًا، واضبط active_trips_only على true، واضبط minimum_staleness على وقت أكبر من معظم مُدد الرحلات. على سبيل المثال، يمكنك استخدام ساعة واحدة. تشتمل النتائج على الرحلات التي لم يتم كاملة أو تم إلغاؤها، ولم يتم تحديثها منذ أكثر من ساعة. يجب على موفّر الخدمة فحص هذه الرحلات للتأكد من تحديث حالتها في Fleet Engine بشكل صحيح.

تحديد المشاكل وحلّها

في حال حدوث خطأ DEADLINE_EXCEEDED، تكون حالة Fleet Engine غير معروفة. على موفّر الخدمة الاتصال بـ CreateTrip مرة أخرى، والذي يعرض 201 (CREATED) أو 409 (CONFLICT). في الحالة الثانية، نجح الطلب السابق قبل DEADLINE_EXCEEDED. راجِع أدلة واجهة برمجة التطبيقات للمستهلكين لمزيد من المعلومات حول التعامل مع أخطاء الرحلات: Android أو iOS.

دعم بشأن رحلات مشاركة السيارة

يمكنك تحديد رحلات "SHARED" متعددة إلى مركبة تتيح استخدام "TripType.SHARED". عليك تحديد ترتيب جميع نقاط المسار التي لم يتم تجاوزها لجميع الرحلات المخصّصة للمركبة في هذه الرحلة المشتركة عبر Trip.vehicle_waypoints عند تحديد vehicle_id لرحلة مشترَكة (في طلب CreateTrip أو UpdateTrip). راجِع القسم vehicle_waypoints للاطّلاع على استدعاء الإجراءات عن بُعد أو vehicleWaypoints لـ REST.

توفّر الوجهات المتعددة

تحديد وجهة وسيطة

يتم دمج الحقل intermediateDestinations والحقل intermediateDestinationIndex في الرحلة (RPC | REST) للإشارة إلى الوجهة.

تعديل الوجهة المتوسطة

ويمكنك تعديل الوجهات المتوسطة من خلال UpdateTrip. عند تعديل الوجهات المتوسطة، يجب تقديم قائمة كاملة بالوجهات الوسيطة، بما في ذلك تلك التي تمت زيارتها، وليس فقط الوجهة التي تمت إضافتها أو سيتم تعديلها مؤخرًا. عندما يشير intermediateDestinationIndex إلى فهرس بعد موضع الوجهة المتوسطة المضافة أو المعدَّلة حديثًا، لن تتم إضافة الوجهة الوسيطة الجديدة أو المعدَّلة إلى waypoints الخاصة بالمركبة أو remainingWaypoints الخاصة بالرحلة. السبب هو أنّه يتم التعامل مع أي وجهات وسيطة قبل intermediateDestinationIndex على أنّها سبق أن تمت زيارتها.

التغييرات على حالة الرحلة

يجب ملء الحقل intermediateDestinationsVersion في (RPC | REST) في طلب تعديل حالة الرحلة الذي تم إرساله إلى Fleet Engine للإشارة إلى اجتياز وجهة وسيطة. ويتمّ تحديد الوجهة المتوسطة المستهدَفة من خلال الحقل intermediateDestinationIndex. عندما تكون قيمة الحقل "tripStatus" (RPC | REST) هي ENROUTE_TO_INTERMEDIATE_Destination، يشير الرقم بين [0..N-1] إلى الوجهة الوسيطة التي ستعبر المركبة بعد ذلك. عندما تكون قيمة tripStatus هي ARRIVED_AT_INTERMEDIATE_{9/}، يشير الرقم بين [0..N-1] إلى الوجهة الوسيطة التي تصل إليها المركبة.

مثال

يوضح مثال الرمز التالي كيفية تحديث حالة رحلة للسير إلى وجهتها الوسيطة الأولى، بافتراض أنك أنشأت رحلة متعددة الوجهات واجتازت الرحلة نقطة الركوب.

Java

static final String PROJECT_ID = "project-id";
static final String TRIP_ID = "multi-destination-trip-A";

String tripName = "providers/" + PROJECT_ID + "/trips/" + TRIP_ID;
Trip trip = …; // Fetch trip object from FleetEngine or your storage.

TripServiceBlockingStub tripService = TripService.newBlockingStub(channel);

// Trip settings to update.
Trip trip = Trip.newBuilder()
    // Trip status cannot go back to a previous status once it is passed
    .setTripStatus(TripStatus.ENROUTE_TO_INTERMEDIATE_DESTINATION)
    // Enrouting to the first intermediate destination.
    .setIntermediateDestinationIndex(0)
    // intermediate_destinations_version MUST be provided to ensure you
    // have the same picture on intermediate destinations list as FleetEngine has.
    .setIntermediateDestinationsVersion(
        trip.getIntermediateDestinationsVersion())
    .build();

// Trip update request
UpdateTripRequest updateTripRequest =
    UpdateTripRequest.newBuilder()
        .setName(tripName)
        .setTrip(trip)
        .setUpdateMask(
            FieldMask.newBuilder()
                .addPaths("trip_status")
                .addPaths("intermediate_destination_index")
                // intermediate_destinations_version must not be in the
                // update mask.
                .build())
        .build();

// Error handling
try {
  Trip updatedTrip = tripService.updateTrip(updateTripRequest);
} catch (StatusRuntimeException e) {
  Status s = e.getStatus();
  switch (s.getCode()) {
    case NOT_FOUND:  // Trip does not exist.
      break;
    case FAILED_PRECONDITION:  // The given trip status is invalid, or the
                                // intermediate_destinations_version
                                // doesn’t match FleetEngine’s.
      break;
    case PERMISSION_DENIED:
      break;
  }
  return;
}

طريقة التنفيذ: الاشتراك في رسائل الإشعارات من Fleet Engine API

تستخدم واجهة Fleet Engine API خدمة Google Cloud Pub/Sub لنشر إشعارات حول الموضوع الذي أنشأه مشروع Google Cloud للمستهلك. لا يتم تفعيل ميزة "النشر/الاشتراك" تلقائيًا في Fleet Engine في مشروعك على Google Cloud. يُرجى تقديم حالة دعم أو التواصل مع مهندس العملاء لتفعيل ميزة النشر/الاشتراك.

لإنشاء موضوع في مشروع Cloud، اتّبِع هذه التعليمات. يجب أن يكون رقم تعريف الموضوع هو "fleet_engine_notifications".

يجب إنشاء الموضوع في المشروع نفسه على السحابة الإلكترونية الذي يستدعي واجهات برمجة التطبيقات Fleet Engine.

بعد إنشاء الموضوع، عليك منح واجهة Fleet Engine API الإذن بالنشر حول الموضوع. للقيام بذلك، انقر على الموضوع الذي أنشأته للتو وأضف إذنًا جديدًا. قد تحتاج إلى النقر على عرض لوحة المعلومات لفتح محرِّر الأذونات. يجب أن يكون المدير الرئيسي "geo-fleet-engine@system.gserviceaccount.com" ويجب أن يكون الدور Pub/Sub publisher.

لإعداد مشروع Cloud للاشتراك في الإشعارات، اتّبِع هذه التعليمات.

ستنشر Fleet Engine API كل إشعار بتنسيقَي بيانات مختلفَين، protobuf وjson. يتم توضيح تنسيق البيانات لكل إشعار في سمات PubsubMessage باستخدام المفتاح data_format والقيمة protobuf أو json.

مخطط الإشعارات:

بروتوبوف

// A batch of notifications that is published by the Fleet Engine service using
// Cloud Pub/Sub in a single PubsubMessage.
message BatchNotification {
  // Required. At least one notification must exist.
  // List of notifications containing information related to changes in
  // Fleet Engine data.
  repeated Notification notifications = 1;
}

// A notification related to changes in Fleet Engine data.
// The data provides additional information specific to the type of the
// notification.
message Notification {
  // Required. At least one type must exist.
  // Type of notification.
  oneof type {
    // Notification related to changes in vehicle data.
    VehicleNotification vehicle_notification = 1;
  }
}

// Notification sent when a new vehicle was created.
message CreateVehicleNotification {
  // Required.
  // Vehicle must contain all fields that were set when it was created.
  Vehicle vehicle = 1;
}

// Notification sent when an existing vehicle is updated.
message UpdateVehicleNotification {
  // Required.
  // Vehicle must only contain name and fields that are present in the
  // field_mask field below.
  Vehicle vehicle = 1;

  // Required.
  // Contains vehicle field paths that were specifically requested
  // by the Provider.
  google.protobuf.FieldMask field_mask = 2;
}

// Notification related to changes in vehicle data.
message VehicleNotification {
  // Required. At least one type must be set.
  // Type of notification.
  oneof type {
    // Notification sent when a new vehicle was created.
    CreateVehicleNotification create_notification = 1;
    // Notification sent when an existing vehicle is updated.
    UpdateVehicleNotification update_notification = 2;
  }
}

JSON

BatchNotification: {
  "description": "A batch of notifications that is published by the Fleet Engine service using Cloud Pub/Sub in a single PubsubMessage.",
  "type": "object",
  "required": ["notifications"],
  "properties": {
    "notifications": {
      "description": "At least one notification must exist. List of notifications containing information related to changes in Fleet Engine data.",
      "type": "Notification[]"
    }
  }
}

Notification: {
  "description": "A notification related to changes in Fleet Engine data. The data provides additional information specific to the type of the notification.",
  "type": "object",
  "properties": {
    "vehicleNotification": {
      "description": "Notification related to changes in vehicle data.",
      "type": "VehicleNotification"
    }
  }
}

VehicleNotification: {
  "description": "Notification related to changes in vehicle data.",
  "type": "object",
  "properties": {
    "createNotification": {
      "description": "Notification sent when a new vehicle was created.",
      "type": "CreateVehicleNotification"
    },
    "updateNotification": {
      "description": "Notification sent when an existing vehicle is updated.",
      "type": "UpdateVehicleNotification"
    }
  }
}

CreateVehicleNotification: {
  "description": "Notification sent when a new vehicle was created.",
  "type": "object",
  "required": ["vehicle"],
  "properties": {
    "vehicle": {
      "description": "Vehicle must contain all fields that were set when it was created.",
      "type": "Vehicle"
    }
  }
}

UpdateVehicleNotification: {
  "description": "Notification sent when an existing vehicle is updated.",
  "type": "object",
  "required": ["vehicle", "fieldMask"],
  "properties": {
    "vehicle": {
      "description": "Vehicle must only contain name and fields that are present in the fieldMask field below.",
      "type": "Vehicle"
    },
    "fieldMask": {
      "description": "Contains vehicle field paths that were specifically requested by the Provider.",
      "type": "FieldMask"
    }
  }
}