File manager - Edit - /var/www/html/portalHomolog/app/Protobuf/GtfsRealtimeEncoder.php
Back
<?php namespace App\Protobuf; /** * Encoder manual para GTFS-Realtime VehiclePositions em Protocol Buffers. * * Implementa o subset mínimo do wire format necessário para gerar * um FeedMessage com VehiclePosition compatível com a especificação * oficial do Google Transit (gtfs-realtime.proto). * * @see https://gtfs.org/documentation/realtime/proto/ */ class GtfsRealtimeEncoder { private const WIRE_VARINT = 0; private const WIRE_LENGTH_DELIMITED = 2; private const WIRE_32BIT = 5; /** * Gera um FeedMessage binário com posições de veículos. * * @param array $vehicles Lista de veículos processados com as chaves: * - entity_id (string) * - latitude (float) * - longitude (float) * - speed (float, m/s) * - timestamp (int, unix) * - vehicle_id (string) * - route_id (string) * - direction_id (int) * @return string Binário Protobuf serializado */ public static function encodeFeedMessage(array $vehicles): string { $header = self::encodeFeedHeader('2.0', time()); $body = self::encodeField(1, self::WIRE_LENGTH_DELIMITED, $header); foreach ($vehicles as $v) { $entity = self::encodeFeedEntity($v); $body .= self::encodeField(2, self::WIRE_LENGTH_DELIMITED, $entity); } return $body; } private static function encodeFeedHeader(string $version, int $timestamp): string { $data = self::encodeField(1, self::WIRE_LENGTH_DELIMITED, $version); $data .= self::encodeField(3, self::WIRE_VARINT, $timestamp); return $data; } private static function encodeFeedEntity(array $v): string { $data = self::encodeField(1, self::WIRE_LENGTH_DELIMITED, (string) $v['entity_id']); $vehiclePosition = self::encodeVehiclePosition($v); $data .= self::encodeField(4, self::WIRE_LENGTH_DELIMITED, $vehiclePosition); return $data; } private static function encodeVehiclePosition(array $v): string { $trip = self::encodeTripDescriptor( (string) $v['route_id'], (int) $v['direction_id'] ); $position = self::encodePosition( (float) $v['latitude'], (float) $v['longitude'], isset($v['speed']) ? (float) $v['speed'] : null ); $vehicleDescriptor = self::encodeVehicleDescriptor((string) $v['vehicle_id']); $data = self::encodeField(1, self::WIRE_LENGTH_DELIMITED, $trip); $data .= self::encodeField(2, self::WIRE_LENGTH_DELIMITED, $position); $data .= self::encodeField(5, self::WIRE_VARINT, (int) $v['timestamp']); $data .= self::encodeField(8, self::WIRE_LENGTH_DELIMITED, $vehicleDescriptor); return $data; } private static function encodeTripDescriptor(string $routeId, int $directionId): string { // schedule_relationship = SCHEDULED (0) — field 4, varint $data = self::encodeField(4, self::WIRE_VARINT, 0); $data .= self::encodeField(5, self::WIRE_LENGTH_DELIMITED, $routeId); $data .= self::encodeField(6, self::WIRE_VARINT, $directionId); return $data; } private static function encodePosition(float $lat, float $lon, ?float $speed): string { $data = self::encodeField(1, self::WIRE_32BIT, $lat); $data .= self::encodeField(2, self::WIRE_32BIT, $lon); if ($speed !== null && $speed >= 0) { $data .= self::encodeField(5, self::WIRE_32BIT, $speed); } return $data; } private static function encodeVehicleDescriptor(string $id): string { return self::encodeField(1, self::WIRE_LENGTH_DELIMITED, $id); } /** * Codifica um campo Protobuf (tag + value) conforme o wire type. */ private static function encodeField(int $fieldNumber, int $wireType, mixed $value): string { $tag = self::encodeVarint(($fieldNumber << 3) | $wireType); return match ($wireType) { self::WIRE_VARINT => $tag . self::encodeVarint((int) $value), self::WIRE_LENGTH_DELIMITED => $tag . self::encodeLengthDelimited($value), self::WIRE_32BIT => $tag . self::encodeFloat32((float) $value), }; } private static function encodeVarint(int $value): string { if ($value === 0) { return chr(0); } $result = ''; while ($value > 0) { $byte = $value & 0x7F; $value >>= 7; if ($value > 0) { $byte |= 0x80; } $result .= chr($byte); } return $result; } /** * Codifica string ou mensagem embarcada como length-delimited. */ private static function encodeLengthDelimited(string $data): string { return self::encodeVarint(strlen($data)) . $data; } private static function encodeFloat32(float $value): string { return pack('g', $value); } }
| ver. 1.4 |
Github
|
.
| PHP 8.3.28 | Generation time: 0.02 |
proxy
|
phpinfo
|
Settings