BUG 包廂控制畫面開不啟來問題
加入驗証包廂是否在線 20250605
This commit is contained in:
parent
ae6742575d
commit
13b5e3e3e1
49
app/Console/Commands/CheckRoomOnlineStatus.php
Normal file
49
app/Console/Commands/CheckRoomOnlineStatus.php
Normal file
@ -0,0 +1,49 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Console\Commands;
|
||||||
|
|
||||||
|
use Illuminate\Console\Command;
|
||||||
|
use App\Models\Room;
|
||||||
|
use App\Models\MachineStatus;
|
||||||
|
use App\Enums\RoomStatus;
|
||||||
|
use Carbon\Carbon;
|
||||||
|
use App\Services\MachineStatusForwarder;
|
||||||
|
|
||||||
|
class CheckRoomOnlineStatus extends Command
|
||||||
|
{
|
||||||
|
protected $signature = 'rooms:check-online-status';
|
||||||
|
protected $description = 'Check if each room has recent MachineStatus data, mark offline if outdated';
|
||||||
|
|
||||||
|
public function handle()
|
||||||
|
{
|
||||||
|
$now = Carbon::now();
|
||||||
|
$threshold = $now->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;
|
||||||
|
}
|
||||||
|
}
|
@ -8,6 +8,7 @@ use App\Http\Requests\ReceiveRoomStatusDataRequest;
|
|||||||
use App\Services\TcpSocketClient;
|
use App\Services\TcpSocketClient;
|
||||||
use Illuminate\Http\JsonResponse;
|
use Illuminate\Http\JsonResponse;
|
||||||
use Illuminate\Support\Facades\Auth;
|
use Illuminate\Support\Facades\Auth;
|
||||||
|
use App\Services\MachineStatusForwarder;
|
||||||
use App\Services\ApiClient;
|
use App\Services\ApiClient;
|
||||||
use App\Models\User;
|
use App\Models\User;
|
||||||
use App\Models\Branch;
|
use App\Models\Branch;
|
||||||
@ -201,8 +202,7 @@ class RoomControlController extends Controller
|
|||||||
$room->save();
|
$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([
|
return ApiResponse::success([
|
||||||
'data' => MachineStatus::create($validated),
|
'data' => MachineStatus::create($validated),
|
||||||
@ -311,36 +311,7 @@ class RoomControlController extends Controller
|
|||||||
$room->started_at=$validated['started_at'];
|
$room->started_at=$validated['started_at'];
|
||||||
$room->ended_at=$validated['ended_at'];
|
$room->ended_at=$validated['ended_at'];
|
||||||
$room->save();
|
$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);
|
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;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
@ -28,7 +28,7 @@ class RoomDetailModal extends Component
|
|||||||
{
|
{
|
||||||
$room = Room::find($roomId);
|
$room = Room::find($roomId);
|
||||||
$this->room_name=$room->type->value . $room->name;
|
$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;
|
$this->showModal = true;
|
||||||
}
|
}
|
||||||
public function closeModal()
|
public function closeModal()
|
||||||
|
54
app/Services/MachineStatusForwarder.php
Normal file
54
app/Services/MachineStatusForwarder.php
Normal file
@ -0,0 +1,54 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Services;
|
||||||
|
|
||||||
|
use App\Models\User;
|
||||||
|
use Illuminate\Support\Facades\Log;
|
||||||
|
use Illuminate\Http\Client\Response;
|
||||||
|
use App\Services\ApiClient;
|
||||||
|
|
||||||
|
class MachineStatusForwarder
|
||||||
|
{
|
||||||
|
protected string $externalUrl;
|
||||||
|
protected string $endpoint;
|
||||||
|
protected array $validated;
|
||||||
|
protected ?User $user = null;
|
||||||
|
|
||||||
|
public function __construct(string $externalUrl, string $endpoint, array $validated)
|
||||||
|
{
|
||||||
|
$this->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;
|
||||||
|
}
|
||||||
|
}
|
@ -13,7 +13,7 @@
|
|||||||
</button>
|
</button>
|
||||||
</x-slot>
|
</x-slot>
|
||||||
<x-slot name="title">
|
<x-slot name="title">
|
||||||
{{ $room->name ?? '未選擇' }}包廂設定
|
{{ $room_name ?? '未選擇' }}包廂設定
|
||||||
</x-slot>
|
</x-slot>
|
||||||
<div class="grid grid-cols-3 gap-4 mb-4">
|
<div class="grid grid-cols-3 gap-4 mb-4">
|
||||||
<x-wireui:button wire:click="startNotify" >開機</x-wireui:button>
|
<x-wireui:button wire:click="startNotify" >開機</x-wireui:button>
|
||||||
|
@ -3,11 +3,12 @@
|
|||||||
use Illuminate\Foundation\Inspiring;
|
use Illuminate\Foundation\Inspiring;
|
||||||
use Illuminate\Support\Facades\Artisan;
|
use Illuminate\Support\Facades\Artisan;
|
||||||
|
|
||||||
Artisan::command('inspire', function () {
|
//Artisan::command('inspire', function () {
|
||||||
$this->comment(Inspiring::quote());
|
// $this->comment(Inspiring::quote());
|
||||||
})->purpose('Display an inspiring quote');
|
//})->purpose('Display an inspiring quote');
|
||||||
|
|
||||||
Schedule::command('app:clear-machine-statuses')->dailyAt('12:00'); // 每天凌晨 12:10 執行
|
Schedule::command('app:clear-machine-statuses')->dailyAt('12:00'); // 每天凌晨 12:10 執行
|
||||||
|
Schedule::command('rooms:check-online-status')->everyMinute(); //每分驗証
|
||||||
//首次部署或有新增命令時)建立或更新任務排程 Crontab
|
//首次部署或有新增命令時)建立或更新任務排程 Crontab
|
||||||
// 檢查是否已有下列 crontab 設定(crontab -e):
|
// 檢查是否已有下列 crontab 設定(crontab -e):
|
||||||
//分鐘 小時 日 月 星期 指令
|
//分鐘 小時 日 月 星期 指令
|
||||||
|
Loading…
x
Reference in New Issue
Block a user