diff --git a/app/Console/Commands/CheckRoomOnlineStatus.php b/app/Console/Commands/CheckRoomOnlineStatus.php
new file mode 100644
index 0000000..ed507d2
--- /dev/null
+++ b/app/Console/Commands/CheckRoomOnlineStatus.php
@@ -0,0 +1,49 @@
+subMinutes(10);
+
+ // 所有房間
+ $rooms = Room::with('branch')->where('is_online',1)->get();
+
+ foreach ($rooms as $room) {
+ // 找出最近的一筆 MachineStatus 資料(比對 hostname 和 branch_name)
+ $latestStatus = MachineStatus::where('hostname', $room->type->value.$room->name)
+ //->where('branch_name', optional($room->branch)->name)
+ ->latest('created_at')
+ ->first();
+
+ if (!$latestStatus || $latestStatus->created_at < $threshold) {
+ $room->is_online = false;
+ $room->status = RoomStatus::Error;
+ $room->save();
+
+ $response = (new MachineStatusForwarder($rooms->branch->external_ip, "/api/room/receiveSwitch", [
+ "branch_name"=>$rooms->branch->name,
+ "room_name"=>$rooms->type->value.$rooms->name,
+ "command" =>"error",
+
+ ]))->forward();
+ $this->info("Room [{$room->name}] marked as offline (no recent MachineStatus)");
+ }
+ }
+
+ return 0;
+ }
+}
\ No newline at end of file
diff --git a/app/Http/Controllers/RoomControlController.php b/app/Http/Controllers/RoomControlController.php
index 6fd2287..54b738f 100644
--- a/app/Http/Controllers/RoomControlController.php
+++ b/app/Http/Controllers/RoomControlController.php
@@ -8,6 +8,7 @@ use App\Http\Requests\ReceiveRoomStatusDataRequest;
use App\Services\TcpSocketClient;
use Illuminate\Http\JsonResponse;
use Illuminate\Support\Facades\Auth;
+use App\Services\MachineStatusForwarder;
use App\Services\ApiClient;
use App\Models\User;
use App\Models\Branch;
@@ -201,8 +202,7 @@ class RoomControlController extends Controller
$room->save();
}
- $this->receiveRequest($branch->external_ip,"/api/room/heartbeat", $validated);
-
+ $response = (new MachineStatusForwarder($branch->external_ip, "/api/room/heartbeat", $validated))->forward();
return ApiResponse::success([
'data' => MachineStatus::create($validated),
@@ -311,36 +311,7 @@ class RoomControlController extends Controller
$room->started_at=$validated['started_at'];
$room->ended_at=$validated['ended_at'];
$room->save();
- $this->receiveRequest($branch->external_ip,"/api/room/receiveSwitch",$validated);
+ $response = (new MachineStatusForwarder($branch->external_ip, "/api/room/receiveSwitch", $validated))->forward();
return $validated['command']==='error' ? ApiResponse::error('機房控制失敗') : ApiResponse::success($room);
}
-
- function receiveRequest(string $externalUrl,string $endpoint, array $validated){
- $response=null;
- $parsed = parse_url($externalUrl);
- $hostParts = explode('.', $parsed['host']);
-
- if (count($hostParts) >= 3) {
- $mainDomain = implode('.', array_slice($hostParts, 1));
- } else {
- $mainDomain = $parsed['host'];
- }
-
- $mainDomainUrl= $parsed['scheme'] . '://' . $mainDomain;
- $user = User::find(2);
- if ($user && $user->api_plain_token) {
- $client = (new ApiClient($mainDomainUrl, $user->api_plain_token));
- $response = $client->post($endpoint, $validated);
-
- Log::info('✅ Machine status forwarded', [
- 'endpoint' => $endpoint,
- 'request' => $validated,
- 'status' => $response->status(),
- 'body' => $response->json(),
- ]);
- } else {
- Log::warning("🔒 User with ID {$userId} not found or missing token");
- }
- return $response;
- }
}
diff --git a/app/Livewire/Admin/RoomDetailModal.php b/app/Livewire/Admin/RoomDetailModal.php
index ee4c453..91e13ce 100644
--- a/app/Livewire/Admin/RoomDetailModal.php
+++ b/app/Livewire/Admin/RoomDetailModal.php
@@ -28,7 +28,7 @@ class RoomDetailModal extends Component
{
$room = Room::find($roomId);
$this->room_name=$room->type->value . $room->name;
- $this->branch = Branch::find($this->room->branch_id);
+ $this->branch = Branch::find($room->branch_id);
$this->showModal = true;
}
public function closeModal()
diff --git a/app/Services/MachineStatusForwarder.php b/app/Services/MachineStatusForwarder.php
new file mode 100644
index 0000000..e516d41
--- /dev/null
+++ b/app/Services/MachineStatusForwarder.php
@@ -0,0 +1,54 @@
+externalUrl = $externalUrl;
+ $this->endpoint = $endpoint;
+ $this->validated = $validated;
+ }
+
+ public function forward(): ?Response
+ {
+ $response = null;
+ $parsed = parse_url($this->externalUrl);
+ $hostParts = explode('.', $parsed['host']);
+
+ $mainDomain = count($hostParts) >= 3
+ ? implode('.', array_slice($hostParts, 1))
+ : $parsed['host'];
+
+ $mainDomainUrl = "{$parsed['scheme']}://{$mainDomain}";
+
+ $this->user = User::find(2); // 或用 dependency injection 把 User 帶進來
+
+ if ($this->user && $this->user->api_plain_token) {
+ $client = new ApiClient($mainDomainUrl, $this->user->api_plain_token);
+ $response = $client->post($this->endpoint, $this->validated);
+
+ Log::info('✅ Machine status forwarded', [
+ 'endpoint' => $this->endpoint,
+ 'request' => $this->validated,
+ 'status' => $response->status(),
+ 'body' => $response->json(),
+ ]);
+ } else {
+ Log::warning("🔒 User with ID 2 not found or missing token");
+ }
+
+ return $response;
+ }
+}
\ No newline at end of file
diff --git a/resources/views/livewire/admin/room-detail-modal.blade.php b/resources/views/livewire/admin/room-detail-modal.blade.php
index abda927..2ac52f5 100644
--- a/resources/views/livewire/admin/room-detail-modal.blade.php
+++ b/resources/views/livewire/admin/room-detail-modal.blade.php
@@ -13,7 +13,7 @@