only('email', 'password'); if (!Auth::attempt($credentials)) { return ApiResponse::unauthorized(); } // 2. 取得登入使用者 $user = Auth::user(); // 3. 產生或取得 Token if (empty($user->api_plain_token)) { $token = $user->createToken('pc-heartbeat')->plainTextToken; $user->api_plain_token = $token; $user->save(); } else { $token = $user->api_plain_token; } // 4. 驗證其他註冊欄位 $validated = $request->validated(); // branch_id, room_name, room_ip // 5. 找出對應包廂 $room = Room::where('branch_id', $validated['branch_id']) ->where('name', $validated['room_name']) ->first(); if (!$room) { return ApiResponse::error('找不到對應包廂'); } // 6. 更新包廂資訊 $room->internal_ip = $request->ip(); $room->port = 1000; // 預設值 $room->is_online =1; $room->status = RoomStatus::Closed; $room->touch(); // 更新 updated_at $room->save(); // 7. 回傳 token 與包廂資料 return ApiResponse::success([ 'token' => $token, 'room' => $room, ]); } public function StatusReport(ReceiveRoomStatusRequest $request) { $data = $request->validate([ 'hostname' => 'required|string', 'ip' => 'required|string', 'cpu' => 'nullable|numeric', 'memory' => 'nullable|numeric', 'disk' => 'nullable|numeric', 'status' => 'required|string', ]); } /** * @OA\Post( * path="/api/room/sendSwitch", * summary="送出包廂控制指令", * description="依據傳入的 room_id 與 command,透過 TCP 傳送對應指令給包廂電腦。", * operationId="sendRoomSwitchCommand", * tags={"Room Control"}, * security={{"Authorization":{}}}, * @OA\RequestBody( * required=true, * @OA\JsonContent(ref="#/components/schemas/SendRoomSwitchCommandRequest") * ), * @OA\Response( * response=200, * description="成功傳送指令並回傳 TCP 回應", * @OA\JsonContent( * allOf={ * @OA\Schema(ref="#/components/schemas/ApiResponse"), * @OA\Schema( * @OA\Property(property="data", ref="#/components/schemas/Room") * ) * } * ) * ), * @OA\Response( * response=401, * description="Unauthorized", * @OA\JsonContent( * allOf={ * @OA\Schema(ref="#/components/schemas/ApiResponse"), * @OA\Schema( * @OA\Property(property="code", type="string", example="UNAUTHORIZED"), * @OA\Property(property="message", type="string", example="Unauthorized"), * @OA\Property(property="data", type="null") * ) * } * ) * ), * @OA\Parameter( * name="Accept", * in="header", * required=true, * @OA\Schema(type="string", default="application/json") * ) * ) */ public function sendSwitch(SendRoomSwitchCommandRequest $request): JsonResponse { $validated = $request->validated(); $room = Room::where([ ['branch_id', $validated['branch_id']], ['name', $validated['room_name']], ])->first(); if (!$room) { return ApiResponse::error('房間不存在'); } // 檢查必要欄位是否缺失或狀態為錯誤 if (empty($room->internal_ip) || empty($room->port)) { return ApiResponse::error('房間未設定 IP 或 Port'); } if ($room->status === RoomStatus::Error) { return ApiResponse::error('房間目前處於錯誤狀態,無法操作'); } $suffix = substr($room->name, -3) ?: $room->name; $signal = match ($validated['command']) { 'active' => 'O', 'closed' => 'X', 'fire' => 'F', default => 'X', // fallback 保險起見 }; $data = $suffix . "," . $signal; //dd($data); $client = new TcpSocketClient($room->internal_ip, $room->port); try { $response = $client->send($data); $room->status=$validated['command']; $room->started_at=$validated['started_at']; $room->ended_at=$validated['ended_at']; $room->save(); return ApiResponse::success($room); } catch (\Throwable $e) { $room->status=RoomStatus::Error; $room->started_at=null; $room->ended_at=null; $room->save(); return ApiResponse::error($e->getMessage()); } } }