Update: 2026-07-12 05:40:28
This commit is contained in:
@@ -182,6 +182,61 @@ function forwardLocationToPassengerSocket(
|
||||
);
|
||||
}
|
||||
|
||||
// ============================================================
|
||||
// 🚌 Forward موقع الباص → سيرفر الراكب (بثّ لغرفة الخط، ASYNC + throttle)
|
||||
// نفس آلية forwardLocationToPassengerSocket لكن للبثّ الجماعي
|
||||
// (باص واحد → كل ركاب الخط) بدل (سائق → راكب واحد)
|
||||
// ============================================================
|
||||
function forwardBusLocationToRoute(
|
||||
int $tripId,
|
||||
int $routeId,
|
||||
array $payload,
|
||||
string $internalKey,
|
||||
array &$busThrottle
|
||||
): void {
|
||||
if ($routeId <= 0) return;
|
||||
|
||||
$now = time();
|
||||
$last = $busThrottle[$tripId] ?? null;
|
||||
|
||||
if ($last !== null) {
|
||||
$timeDiff = $now - $last['ts'];
|
||||
$dist = haversineDistance(
|
||||
$last['lat'], $last['lng'],
|
||||
(float)$payload['latitude'], (float)$payload['longitude']
|
||||
);
|
||||
if ($dist < FORWARD_MIN_METERS && $timeDiff < FORWARD_MAX_SECONDS) return;
|
||||
}
|
||||
|
||||
$busThrottle[$tripId] = [
|
||||
'ts' => $now,
|
||||
'lat' => (float)$payload['latitude'],
|
||||
'lng' => (float)$payload['longitude'],
|
||||
];
|
||||
|
||||
$passengerSocketUrl = getenv('PASSENGER_SOCKET_INTERNAL_URL') ?: 'http://127.0.0.1:3031';
|
||||
$http = new AsyncHttp();
|
||||
$http->request(
|
||||
$passengerSocketUrl,
|
||||
[
|
||||
'method' => 'POST',
|
||||
'data' => http_build_query([
|
||||
'action' => 'broadcast_bus_location',
|
||||
'route_id' => $routeId,
|
||||
'payload' => json_encode($payload),
|
||||
]),
|
||||
'headers' => [
|
||||
'Content-Type' => 'application/x-www-form-urlencoded',
|
||||
'x-internal-key' => $internalKey,
|
||||
'Connection' => 'close',
|
||||
],
|
||||
'timeout' => 3,
|
||||
],
|
||||
null,
|
||||
fn(\Exception $e) => logMsg('⚠️ Bus forward failed: ' . $e->getMessage())
|
||||
);
|
||||
}
|
||||
|
||||
// ============================================================
|
||||
// 📲 FCM (ASYNC)
|
||||
// ============================================================
|
||||
@@ -215,9 +270,10 @@ function sendFCM_Async(string $token, string $title, string $body, array $rideDa
|
||||
// ============================================================
|
||||
$connectedDrivers = [];
|
||||
$active_orders_drivers = [];
|
||||
$driverState = [];
|
||||
$fwdThrottle = [];
|
||||
$driverState = [];
|
||||
$fwdThrottle = [];
|
||||
$eventBuffer = []; // 🚀 Level 2: مصفوفة تجميع الأحداث لـ Redis
|
||||
$busFwdThrottle = []; // 🚌 throttle بثّ موقع الباص لكل رحلة (trip_id)
|
||||
|
||||
// ============================================================
|
||||
// 🚀 Socket.IO — بورت 2020
|
||||
@@ -592,6 +648,21 @@ $io->on('workerStart', function () use ($io, $INTERNAL_KEY) {
|
||||
$connection->send('Error');
|
||||
}
|
||||
|
||||
// ── 8. 🚌 Get Bus Position (آخر موقع للباص — للتحميل الأولي) ─
|
||||
// يستدعيه الباك اند (transit/trip/live.php) ليعطي الراكب آخر
|
||||
// موقع معروف فوراً عند فتح الخط، قبل أول بثّ حي عبر السوكت.
|
||||
} elseif ($action === 'get_bus_position') {
|
||||
$tripId = (int)($post['trip_id'] ?? 0);
|
||||
if ($tripId <= 0 || !$redis) {
|
||||
$connection->send(json_encode(['status' => false, 'data' => null]));
|
||||
return;
|
||||
}
|
||||
$pos = $redis->hgetall("transit:trip:$tripId:pos");
|
||||
$connection->send(json_encode([
|
||||
'status' => !empty($pos),
|
||||
'data' => $pos ?: null,
|
||||
]));
|
||||
|
||||
} else {
|
||||
$connection->send('Unknown action');
|
||||
}
|
||||
@@ -604,7 +675,7 @@ $io->on('workerStart', function () use ($io, $INTERNAL_KEY) {
|
||||
// B. WebSocket Events للسائقين
|
||||
// ============================================================
|
||||
$io->on('connection', function ($socket) use ($INTERNAL_KEY) {
|
||||
global $connectedDrivers, $driverState, $fwdThrottle, $eventBuffer;
|
||||
global $connectedDrivers, $driverState, $fwdThrottle, $eventBuffer, $busFwdThrottle;
|
||||
|
||||
$query = $socket->handshake['query'] ?? [];
|
||||
$driverId = $query['driver_id'] ?? null;
|
||||
@@ -826,13 +897,73 @@ $io->on('connection', function ($socket) use ($INTERNAL_KEY) {
|
||||
}
|
||||
});
|
||||
|
||||
// ── 🚌 وضع الباص (مواصلاتي) ────────────────────────────────
|
||||
// سائق الباص هو سائق عادي (JWT role=driver) لكنه في وضع الباص لا
|
||||
// يدخل حوض الرحلات (geo:drivers:*). يبعث update_bus_location فقط.
|
||||
// نخزّن آخر موقع في Redis سيرفر الموقع + نبثّه لغرفة الخط.
|
||||
$socket->on('update_bus_location', function ($data)
|
||||
use ($driverId, $INTERNAL_KEY, &$busFwdThrottle)
|
||||
{
|
||||
$data = (array) $data;
|
||||
|
||||
$tripId = (int)($data['trip_id'] ?? 0);
|
||||
$lat = isset($data['lat']) ? (float)$data['lat'] : null;
|
||||
$lng = isset($data['lng']) ? (float)$data['lng'] : null;
|
||||
$heading = (float)($data['heading'] ?? 0);
|
||||
$speed = (float)($data['speed'] ?? 0);
|
||||
$stopSeq = isset($data['current_stop_seq']) ? (int)$data['current_stop_seq'] : null;
|
||||
|
||||
if (!$tripId || $lat === null || $lng === null) return;
|
||||
|
||||
$redis = getRedis();
|
||||
if (!$redis) return;
|
||||
|
||||
// ── تحقق الملكية: هذه الرحلة فعلاً مسندة لهذا السائق؟ ────────
|
||||
// الكاش يُكتب من transit/trip/start.php عند بدء الرحلة (transitSetTripOwner)
|
||||
// ويُحذف عند إنهائها. أي سائق آخر (حتى لو خمّن trip_id صحيح) يُرفض هنا،
|
||||
// ولا نثق بـ route_id القادم من العميل — نأخذه دائماً من الكاش الموثوق.
|
||||
$owner = $redis->hgetall("transit:trip:$tripId:owner");
|
||||
if (empty($owner) || (string)($owner['driver_id'] ?? '') !== (string)$driverId) {
|
||||
logMsg("🚫 update_bus_location rejected: driver #$driverId is not the owner of trip #$tripId");
|
||||
return;
|
||||
}
|
||||
$routeId = (int)($owner['route_id'] ?? 0);
|
||||
if ($routeId <= 0) return;
|
||||
|
||||
// 1. آخر موقع في Redis سيرفر الموقع (بدون بادئة — يقرؤه الباك اند عبر $redisLocation)
|
||||
$posKey = "transit:trip:$tripId:pos";
|
||||
$redis->hmset($posKey, [
|
||||
'lat' => $lat,
|
||||
'lng' => $lng,
|
||||
'heading' => $heading,
|
||||
'speed' => $speed,
|
||||
'driver_id' => $driverId,
|
||||
'ts' => time(),
|
||||
]);
|
||||
$redis->expire($posKey, 86400);
|
||||
|
||||
// 2. بثّ الموقع لكل ركاب الخط عبر سيرفر الراكب (throttled)
|
||||
forwardBusLocationToRoute($tripId, $routeId, [
|
||||
'trip_id' => $tripId,
|
||||
'route_id' => $routeId,
|
||||
'latitude' => $lat,
|
||||
'longitude' => $lng,
|
||||
'heading' => $heading,
|
||||
'speed' => $speed,
|
||||
'current_stop_seq' => $stopSeq,
|
||||
'driver_id' => $driverId,
|
||||
], $INTERNAL_KEY, $busFwdThrottle);
|
||||
});
|
||||
|
||||
$socket->on('disconnect', function () use ($driverId) {
|
||||
global $connectedDrivers, $driverState, $fwdThrottle;
|
||||
|
||||
unset($connectedDrivers[$driverId]);
|
||||
unset($driverState[$driverId]);
|
||||
unset($fwdThrottle[$driverId]);
|
||||
|
||||
// ملاحظة: $busFwdThrottle مُفهرس بـ trip_id (لا driver_id) — يُستبدَل
|
||||
// تلقائياً في الرحلة التالية، فلا حاجة لحذفه هنا.
|
||||
|
||||
logMsg("❌ Driver Disconnected: #$driverId");
|
||||
});
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user