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

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

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

لأغراض التطوير، تأكَّد من تثبيت حزمة Cloud 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. اطّلِع على مستندات Cloud Logging لإلقاء نظرة عامة على طريقة قراءة السجلات وتحليلها.

قد لا يتم تفعيل ميزة التسجيل تلقائيًا للمشاريع التي تم إنشاؤها قبل 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
يمنح الإذن بتعديل المواقع الجغرافية للمركبات ومساراتها واسترداد معلومات حول المركبات والرحلات. ويتم عادةً استخدام الرموز المميّزة التي أنشأها حساب خدمة باستخدام هذا الدور من الأجهزة الجوّالة لتطبيق سائق توصيل الرحلات أو مشاركة الرحلات.
مستخدم متميز لخدمة محركات الأسطول

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

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

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 رموز JSON للويب (JWT) لتقييد الوصول إلى واجهات برمجة تطبيقات Fleet Engine. تعمل مكتبة Fleet Engine Auth Library المتاحة على GitHub على تبسيط عملية إنشاء Fleet Engine JWT وتوقيعها بأمان.

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

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

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

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

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

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

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

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

الحقلالوصف
iss عنوان البريد الإلكتروني لحساب الخدمة
sub عنوان البريد الإلكتروني لحساب الخدمة
أُود خدمة SERVICE_NAME لحساب الخدمة، وهي في هذه الحالة https://fleetengine.googleapis.com/
Iat الطابع الزمني الذي تم فيه إنشاء الرمز المميّز والمحدّد بالثواني منذ الساعة 00:00:00 بالتوقيت العالمي المنسَّق، في 1 كانون الثاني (يناير) 1970. انتظر 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 حسب التوقيت العالمي المنسَّق، 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 التالي لتوقيع الرمز المميّز نيابةً عن حساب خدمة المستخدم المميّز:

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 API إدخالاً في السجلّ عبر سجلّات 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 عند إنشاء مركبة جديدة. لتلقّي هذه الإشعارات، يُرجى اتّباع التعليمات الواردة هنا.

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

إذا لم تكن تستخدم Driver 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 امتيازات المستخدم المميز في Fleet Engine.

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

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

مثال

يفعّل هذا المثال 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 API إدخالاً في السجلّ عبر سجلّات 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 قائمة مرتّبة من السائقين الذين يتطابقون مع سمات المهام مع سمات المركبات في أسطولك. لمزيد من المعلومات، راجع العثور على السائقين القريبين.

مثال

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

shell

يجب أولاً تعديل الموقع الجغرافي للمركبة التي أنشأناها في الخطوات السابقة لكي تصبح مؤهلة. في العالم الحقيقي، سيتم إجراء ذلك بواسطة Driver 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 API العثور على جميع المركبات التي تستوفي بعض خيارات الطلبات المحدّدة. تعرض واجهة برمجة التطبيقات 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;
}

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

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

يحتوي 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 المخصّصة للرحلة إلا عندما تكون الحالة NEW أو CANCELED. إذا ألغى سائق رحلة أثناء الطريق، يجب ضبط حالة "الرحلة" على "NEW" أو "CANCELED" قبل تغيير "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_destination، لن تتم إزالة الوجهة المتوسطة الحالية من قائمة نقاط الطريق المتبقية للمركبة حتى تشير السيارة إلى أنها تسير إلى نقطة الطريق التالية.

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

فيديو تعليمات: إنشاء رحلة

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

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

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

عند إنشاء رحلة، يمكنك تقديم 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 تلقائيًا الحقول التالية عند استخدام ميزة "مشاركة الرحلة" من خلال Driver 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.

  • التوفيق بين حالة مقدّم الخدمة وحالة Fleet Engine: يمكن لمقدّم الخدمة استخدام 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 للقيمة RPC أو 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_destination، يشير الرقم بين [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 Google Cloud Pub/Sub لنشر إشعارات حول الموضوع الذي أنشأته مشروع Google Cloud للمستهلك. لا يتم تفعيل ميزة Pub/Sub تلقائيًا في Fleet Engine على مشروعك على Google Cloud. يُرجى تقديم طلب الحصول على الدعم أو التواصل مع مهندس العميل لتفعيل النشر/الاشتراك.

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

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

بعد إنشاء الموضوع، ستحتاج إلى منح إذن 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"
    }
  }
}