findKitchenDevice($token); $this->devices->recordHeartbeat($device); return view('pos.kitchen.public', [ 'device' => $device, 'locationName' => $device->location?->name ?? 'Kitchen', 'stations' => $this->board->stations($device->owner_ref), 'feedUrl' => route('pos.kitchen-display.feed', ['token' => $token]), 'streamUrl' => route('pos.kitchen-display.stream', ['token' => $token]), 'bumpUrl' => route('pos.kitchen-display.bump', ['token' => $token, 'line' => '__ID__']), ]); } public function feed(string $token): JsonResponse { $device = $this->findKitchenDevice($token); $this->devices->recordHeartbeat($device); return response()->json($this->board->payload($device->owner_ref)); } public function stream(Request $request, string $token): StreamedResponse { $device = $this->findKitchenDevice($token); $this->devices->recordHeartbeat($device); $owner = $device->owner_ref; $deviceId = $device->id; $request->session()->save(); $response = new StreamedResponse(function () use ($owner, $deviceId) { while (ob_get_level() > 0) { @ob_end_flush(); } @set_time_limit(0); $start = time(); $lastHash = null; while (true) { if ($deviceId) { $live = PosDevice::query()->find($deviceId); if ($live) { app(DeviceService::class)->recordHeartbeat($live); } } $payload = $this->board->payload($owner); $json = json_encode($payload); $hash = md5((string) $json); if ($hash !== $lastHash) { echo 'data: '.$json."\n\n"; $lastHash = $hash; } else { echo ": ping\n\n"; } @ob_flush(); @flush(); if (connection_aborted() || (time() - $start) >= 25) { break; } sleep(1); } }); $response->headers->set('Content-Type', 'text/event-stream'); $response->headers->set('Cache-Control', 'no-cache'); $response->headers->set('Connection', 'keep-alive'); $response->headers->set('X-Accel-Buffering', 'no'); return $response; } public function bump(string $token, PosSaleLine $line): JsonResponse { $device = $this->findKitchenDevice($token); $this->devices->recordHeartbeat($device); return response()->json($this->board->bumpLine($line, $device->owner_ref)); } private function findKitchenDevice(string $token): PosDevice { $device = $this->devices->findByToken($token); abort_unless($device && $device->type === 'kitchen_display', 404); return $device->loadMissing('location'); } }