You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

出租车调度系统中基于Firebase GCM的多司机请求依次推送方案问询

你的思路完全靠谱!针对这个出租车调度的推送需求,我们可以把这个“依次推送最近3位司机”的思路落地成一套清晰的流程,既能避免Topic广播的多接单问题,又能满足“拒绝后自动推下一位”的要求。下面是具体的实现方案和细节:

可行的实现方案与细节

1. 核心逻辑确认

你提到的“记录最近3位司机,依次发送请求”的思路完全匹配需求:通过精准的单发推送替代广播,每次只给一位司机发请求,直到有人接单或者推完3位为止,完美解决多司机同时接单的问题。

2. 分步骤实现流程

(1)生成候选司机列表并存储

当乘客发起打车请求时:

  • 调用地理位置服务,计算出当前空闲的3位最近司机
  • 给这个打车请求生成唯一的requestId,用来关联所有后续操作
  • 将以下信息存入你的数据库(比如Firebase Realtime Database/Firestore):
    • 乘客信息、请求位置
    • 3位司机的driverId、FCM Token、距离、状态(初始为pending)
    • 当前推送的候选索引(初始为0)
    • 请求的整体状态(初始为active)

(2)触发第一轮推送

从数据库中取出第一位司机的FCM Token,用Firebase的sendToDevice接口发送打车请求通知,同时把该司机的状态更新为notified(标记已推送)。

(3)处理司机的响应

司机端接收到通知后,不管是“接受”还是“拒绝”,都要向你的后端(或Firebase Cloud Functions)发送带requestId和操作类型的请求:

  • 如果司机接单:
    1. 立即把请求的整体状态改为completed
    2. 给另外两位候选司机发送“请求已被他人接单”的通知,更新他们的状态为cancelled
    3. 终止后续推送流程,通知乘客已匹配到司机
  • 如果司机拒绝:
    1. 更新该司机的状态为rejected
    2. 检查候选列表是否还有未推送/未拒绝的司机:
      • 有:取出下一位司机的Token,重复推送流程,同时更新当前候选索引
      • 无:给乘客发送“暂无可用司机”的通知,把请求状态改为failed

(4)超时处理(必加环节)

别忘了处理司机长时间不响应的情况:设置一个超时时间(比如30秒),如果超时未收到司机反馈,自动视为“拒绝”,触发下一位司机的推送。可以用Firebase Cloud Functions的定时触发器,或者后端定时器实现。

3. 关键代码示例(伪代码)

存储候选司机列表(Firestore为例)

// 生成唯一requestId
const requestId = uuid.v4();
// 写入数据库
await db.collection('rideRequests').doc(requestId).set({
  passengerId: 'passenger_123',
  location: { lat: 31.2304, lng: 121.4737 },
  candidates: [
    { driverId: 'driver_001', token: 'fcm_token_001', status: 'pending', distance: 0.6 },
    { driverId: 'driver_002', token: 'fcm_token_002', status: 'pending', distance: 0.9 },
    { driverId: 'driver_003', token: 'fcm_token_003', status: 'pending', distance: 1.3 }
  ],
  currentCandidateIndex: 0,
  requestStatus: 'active'
});

发送FCM通知函数

const admin = require('firebase-admin');

async function sendRideRequest(token, requestId) {
  const message = {
    token: token,
    notification: {
      title: '新打车请求',
      body: '有乘客需要服务,请尽快查看'
    },
    data: {
      requestId: requestId,
      type: 'RIDE_REQUEST'
    }
  };
  await admin.messaging().send(message);
}

处理司机拒绝的云函数

exports.handleDriverRejection = functions.https.onCall(async (data, context) => {
  const { requestId, driverId } = data;
  const requestDoc = db.collection('rideRequests').doc(requestId);
  const requestSnap = await requestDoc.get();

  if (!requestSnap.exists || requestSnap.data().requestStatus !== 'active') {
    return { success: false, msg: '请求已处理' };
  }

  const requestData = requestSnap.data();
  // 更新当前司机状态为rejected
  const updatedCandidates = requestData.candidates.map(c => 
    c.driverId === driverId ? { ...c, status: 'rejected' } : c
  );
  const nextIndex = requestData.currentCandidateIndex + 1;

  if (nextIndex < updatedCandidates.length) {
    // 推送下一位司机
    const nextDriver = updatedCandidates[nextIndex];
    await sendRideRequest(nextDriver.token, requestId);
    // 更新数据库状态
    await requestDoc.update({
      candidates: updatedCandidates,
      currentCandidateIndex: nextIndex
    });
    return { success: true, msg: '已推送至下一位司机' };
  } else {
    // 3位都推完,通知乘客
    await sendPassengerNotification(requestData.passengerId, '暂无可用司机');
    await requestDoc.update({
      candidates: updatedCandidates,
      requestStatus: 'failed'
    });
    return { success: true, msg: '已通知乘客无可用司机' };
  }
});

4. 避坑注意事项

  • FCM Token更新:司机的Token可能会因设备重装、应用更新等变化,所以司机端每次启动都要把最新Token同步到数据库
  • 并发控制:用数据库事务处理请求状态的更新,避免极端情况下两个司机同时接单的冲突
  • 通知清晰度:通知内容要包含乘客位置、距离等关键信息,帮助司机快速决策

内容的提问来源于stack exchange,提问作者Rishabh

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.22 09:30:11