KTV/app/Http/Controllers/RoomControlController.php

328 lines
11 KiB
PHP
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<?php
namespace App\Http\Controllers;
use App\Http\Requests\SendRoomSwitchCommandRequest;
use App\Http\Requests\ReceiveRoomRegisterRequest;
use App\Http\Requests\ReceiveRoomStatusDataRequest;
use App\Services\TcpSocketClient;
use Illuminate\Http\JsonResponse;
use Illuminate\Support\Facades\Auth;
use App\Models\Branch;
use App\Models\Room;
use App\Models\MachineStatus;
use App\Enums\RoomStatus;
use App\Http\Responses\ApiResponse;
use Illuminate\Support\Facades\Log;
/**
* @OA\Tag(
* name="Auth",
* description="包廂控制"
* )
*/
class RoomControlController extends Controller
{
/**
* @OA\Post(
* path="/api/room/receiveRegister",
* summary="包廂註冊控制指令",
* description="依據傳入的 branch_id 與 room_name知道過來的設備來之於那個IP設備。",
* operationId="registerRoomCommand",
* tags={"Room Control"},
* @OA\RequestBody(
* required=true,
* @OA\JsonContent(ref="#/components/schemas/ReceiveRoomRegisterRequest")
* ),
* @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 receiveRegister(ReceiveRoomRegisterRequest $request): JsonResponse
{
$data = $request->only(['branch', 'room_name', 'room_ip', 'email']); // 不記錄密碼
Log::info('Token Request Payload:', $data);
// 1. 驗證帳密(登入用)
$credentials = $request->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. 找出對應包廂
$roomType = null;
$roomName = null;
// 從 room_name例如 PC101, SVR01中擷取 type 與 name
if (preg_match('/^([A-Za-z]+)(\d+)$/', $validated['room_name'], $matches)) {
$roomType = strtolower($matches[1]); // 'PC' → 'pc'
$roomName = $matches[2]; // '101'
}
$branch=Branch::where('name',$validated['branch_name'])->first();
$room = Room::where('branch_id', $branch->id)
->where('name', $roomName)
->where('type', $roomType)
->first();
if (!$room) {
return ApiResponse::error('找不到對應包廂');
}
// 6. 更新包廂資訊
$room->internal_ip = $validated['room_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,
]);
}
/**
* @OA\Post(
* path="/api/room/heartbeat",
* summary="包廂心跳封包指令",
* description="記錄設備連線狀況",
* operationId="heartbeatRoomCommand",
* tags={"Room Control"},
* security={{"Authorization":{}}},
* @OA\RequestBody(
* required=true,
* @OA\JsonContent(ref="#/components/schemas/ReceiveRoomStatusDataRequest")
* ),
* @OA\Response(
* response=200,
* description="成功傳送指令並回傳 TCP 回應",
* @OA\JsonContent(
* allOf={
* @OA\Schema(ref="#/components/schemas/ApiResponse"),
* @OA\Schema(
* @OA\Property(property="data", ref="#/components/schemas/MachineStatus")
* )
* }
* )
* ),
* @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 StatusReport(ReceiveRoomStatusDataRequest $request)
{
$validated = $request->validated();
$roomType = null;
$roomName = null;
// 從 room_name例如 PC101, SVR01中擷取 type 與 name
if (preg_match('/^([A-Za-z]+)(\d+)$/', $validated['hostname'], $matches)) {
$roomType = strtolower($matches[1]); // 'PC' → 'pc'
$roomName = $matches[2]; // '101'
}
$branch=Branch::where('name',$validated['branch_name'])->first();
$room = Room::where('branch_id', $branch->id)
->where('name', $roomName)
->where('type', $roomType)
->first();
// 決定 status 欄位值
$validated['status']= 'error';
if($room){
$validated['status']= 'online';
if($room->internal_ip != $validated['ip']){
$room->internal_ip = $validated['ip'];
$validated['status']='error';
}
$room->is_online=1;
$room->touch(); // 更新 updated_at
$room->save();
}
return ApiResponse::success([
'data' => MachineStatus::create($validated),
]);
}
/**
* @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();
$branch = Branch::where('name',$validated['branch_name'])->first();
$room = Room::where([
['branch_id', $branch->id],
['name', $validated['room_name']],
])->first();
if (!$branch) {
return ApiResponse::error('分店不存在');
}
if (empty($branch->external_ip) ) {
return ApiResponse::error('分店未設定 外部URL');
}
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('房間目前處於錯誤狀態,無法操作');
}
$command = $validated['command'];
$payload = [
'branch_name' => $validated['branch_name'],
'room_name' => $validated['room_name'],
'command' => $command,
'started_at' => $validated['started_at'] ?? null,
'ended_at' => $validated['ended_at'] ?? null,
];
$user = \App\Models\User::find(2);
$token = $user->api_plain_token;
$api = new \App\Services\ApiClient();
$response = $api->setToken($token)->setBaseUrl($branch->external_ip)->post('/room/sendSwitch', $payload);
if (!$response->successful()) {
return ApiResponse::error('指令發送失敗:' . $response->body());
}
return ApiResponse::success("命令已發送:$command");
}
public function receiveSwitch(SendRoomSwitchCommandRequest $request): JsonResponse
{
$validated = $request->validated();
$branch = Branch::where('name',$validated['branch_name'])->first();
$room = Room::where([
['branch_id', $branch->id],
['name', $validated['room_name']],
])->first();
if (!$branch) {
return ApiResponse::error('分店不存在');
}
if (!$room) {
return ApiResponse::error('房間不存在');
}
$room->status=$validated['command'];
$room->started_at=$validated['started_at'];
$room->ended_at=$validated['ended_at'];
$room->save();
return ApiResponse::success($room);
}
}