serialNo = $serialNo; $this->payload = (array) $payload; } /** * Execute the job. */ public function handle(): void { $machine = Machine::withoutGlobalScopes()->where('serial_no', $this->serialNo)->first(); if (!$machine) { Log::warning("MQTT Heartbeat: Machine not found", ['serial_no' => $this->serialNo]); return; } // 更新機台狀態 Log::debug("ProcessHeartbeat: Attempting to set status to online for {$this->serialNo}"); $updateData = [ 'last_heartbeat_at' => now(), 'status' => 'online', ]; // === 狀態異動觸發 (Redis 快取,讓 MQTT 也支援日誌) === $cacheKey = "machine:{$this->serialNo}:state"; $oldState = \Illuminate\Support\Facades\Cache::get($cacheKey); $newState = $oldState ?? []; // 1. 韌體版本比對 (有改才傳,有改才記) if (isset($this->payload['firmware_version'])) { $fv = (string) $this->payload['firmware_version']; if (!isset($oldState['firmware_version']) || (string)$oldState['firmware_version'] !== $fv) { \App\Jobs\Machine\ProcessStateLog::dispatch( $machine->id, $machine->company_id, "Firmware updated to :version", 'info', ['version' => $fv, 'old' => $oldState['firmware_version'] ?? 'Unknown'] ); } $updateData['firmware_version'] = $fv; $newState['firmware_version'] = $fv; } // 2. 溫度更新 (只要有變動就紀錄日誌) if (isset($this->payload['temperature'])) { $temp = (int) $this->payload['temperature']; Log::debug("ProcessHeartbeat: Temperature reported for {$this->serialNo}: {$temp}"); $updateData['temperature'] = $temp; // 讀取最後一次記錄日誌的溫度與時間 $tempLogCacheKey = "machine:{$this->serialNo}:last_temp_log"; $lastLogEntry = \Illuminate\Support\Facades\Cache::get($tempLogCacheKey); $shouldLog = false; if (!$lastLogEntry) { $shouldLog = true; } else { $lastValue = (int) $lastLogEntry['value']; $lastAt = \Carbon\Carbon::parse($lastLogEntry['at']); // 條件 A: 只要溫度與上次記錄不同就記錄 (整數比對) if ($temp !== $lastValue) { Log::debug("ProcessHeartbeat: Temperature changed from {$lastValue} to {$temp}. Triggering log."); $shouldLog = true; } // 條件 B: 距離上次日誌超過 4 小時 (保底機制) if ($lastAt->diffInHours(now()) >= 4) { $shouldLog = true; } } if ($shouldLog) { \App\Jobs\Machine\ProcessStateLog::dispatch( $machine->id, $machine->company_id, "Temperature reported: :temp°C", 'info', ['temp' => $temp] ); // 更新快取,保留 7 天 \Illuminate\Support\Facades\Cache::put($tempLogCacheKey, [ 'value' => $temp, 'at' => now()->toDateTimeString() ], 604800); } } // 更新快取 \Illuminate\Support\Facades\Cache::put($cacheKey, $newState, 86400); $machine->update($updateData); } }