192 lines
6.6 KiB
PHP
192 lines
6.6 KiB
PHP
<?php
|
|
|
|
namespace App\Livewire;
|
|
|
|
use Livewire\Component;
|
|
use App\Services\TraccarService;
|
|
use App\Models\Device;
|
|
use App\Models\Event;
|
|
use App\Models\Position;
|
|
use Illuminate\Support\Facades\Auth;
|
|
use Illuminate\Support\Facades\Cache;
|
|
|
|
class Dashboard extends Component
|
|
{
|
|
public $stats = [];
|
|
public $recentEvents = [];
|
|
public $devicesStatus = [];
|
|
public $mapDevices = [];
|
|
|
|
protected $traccarService;
|
|
|
|
public function boot(TraccarService $traccarService)
|
|
{
|
|
$this->traccarService = $traccarService;
|
|
}
|
|
|
|
public function mount()
|
|
{
|
|
$this->loadDashboardData();
|
|
}
|
|
|
|
public function loadDashboardData()
|
|
{
|
|
$user = Auth::user();
|
|
|
|
// Get user's devices
|
|
$devices = Device::where('user_id', $user->id)->get();
|
|
|
|
// Calculate statistics
|
|
$this->stats = [
|
|
'total_devices' => $devices->count(),
|
|
'online_devices' => $devices->where('status', 'online')->count(),
|
|
'offline_devices' => $devices->where('status', 'offline')->count(),
|
|
'recent_alerts' => Event::whereIn('device_id', $devices->pluck('id'))
|
|
->where('acknowledged', false)
|
|
->where('created_at', '>=', now()->subDays(7))
|
|
->count(),
|
|
];
|
|
|
|
// Get devices status for widgets
|
|
$this->devicesStatus = $devices->map(function ($device) {
|
|
return [
|
|
'id' => $device->id,
|
|
'name' => $device->name,
|
|
'status' => $device->status,
|
|
'last_update' => $device->last_update,
|
|
'is_online' => $device->isOnline(),
|
|
'position' => $device->getLatestPosition(),
|
|
];
|
|
})->toArray();
|
|
|
|
// Get recent events
|
|
$this->recentEvents = Event::with(['device', 'geofence'])
|
|
->whereIn('device_id', $devices->pluck('id'))
|
|
->orderBy('event_time', 'desc')
|
|
->limit(10)
|
|
->get()
|
|
->map(function ($event) {
|
|
return [
|
|
'id' => $event->id,
|
|
'type' => $event->getReadableType(),
|
|
'device_name' => $event->device->name,
|
|
'event_time' => $event->event_time,
|
|
'acknowledged' => $event->acknowledged,
|
|
'severity' => $event->getSeverity(),
|
|
'color' => $event->getEventColor(),
|
|
];
|
|
})->toArray();
|
|
|
|
// Get devices for map display
|
|
$this->mapDevices = $devices->filter(function ($device) {
|
|
return $device->currentPosition && $device->currentPosition->valid;
|
|
})->map(function ($device) {
|
|
$position = $device->currentPosition;
|
|
return [
|
|
'id' => $device->id,
|
|
'name' => $device->name,
|
|
'latitude' => $position->latitude,
|
|
'longitude' => $position->longitude,
|
|
'status' => $device->status,
|
|
'speed' => $position->getFormattedSpeed(),
|
|
'address' => $position->address ?? 'Unknown location',
|
|
'last_update' => $position->device_time,
|
|
];
|
|
})->values()->toArray();
|
|
}
|
|
|
|
public function acknowledgeEvent($eventId)
|
|
{
|
|
$event = Event::find($eventId);
|
|
if ($event && $event->device->user_id === Auth::id()) {
|
|
$event->update([
|
|
'acknowledged' => true,
|
|
'acknowledged_by' => Auth::id(),
|
|
'acknowledged_at' => now(),
|
|
]);
|
|
|
|
$this->loadDashboardData();
|
|
$this->dispatch('event-acknowledged');
|
|
}
|
|
}
|
|
|
|
public function refreshData()
|
|
{
|
|
try {
|
|
// Sync with Traccar API
|
|
$this->syncTraccarData();
|
|
$this->loadDashboardData();
|
|
$this->dispatch('data-refreshed');
|
|
} catch (\Exception $e) {
|
|
$this->dispatch('refresh-error', ['message' => 'Failed to refresh data: ' . $e->getMessage()]);
|
|
}
|
|
}
|
|
|
|
private function syncTraccarData()
|
|
{
|
|
$user = Auth::user();
|
|
|
|
if (!$user->traccar_user_id) {
|
|
return; // User not synced with Traccar
|
|
}
|
|
|
|
// Get latest positions from Traccar
|
|
$positions = $this->traccarService->getPositions();
|
|
|
|
foreach ($positions as $positionData) {
|
|
$device = Device::where('traccar_device_id', $positionData['deviceId'])->first();
|
|
|
|
if ($device && $device->user_id === $user->id) {
|
|
// Update or create position
|
|
$position = Position::updateOrCreate(
|
|
['traccar_position_id' => $positionData['id']],
|
|
[
|
|
'device_id' => $device->id,
|
|
'protocol' => $positionData['protocol'] ?? null,
|
|
'device_time' => $positionData['deviceTime'],
|
|
'fix_time' => $positionData['fixTime'],
|
|
'server_time' => $positionData['serverTime'],
|
|
'outdated' => $positionData['outdated'] ?? false,
|
|
'valid' => $positionData['valid'] ?? true,
|
|
'latitude' => $positionData['latitude'],
|
|
'longitude' => $positionData['longitude'],
|
|
'altitude' => $positionData['altitude'] ?? null,
|
|
'speed' => $positionData['speed'] ?? 0,
|
|
'course' => $positionData['course'] ?? 0,
|
|
'address' => $positionData['address'] ?? null,
|
|
'accuracy' => $positionData['accuracy'] ?? null,
|
|
'attributes' => $positionData['attributes'] ?? null,
|
|
]
|
|
);
|
|
|
|
// Update device status and position
|
|
$device->update([
|
|
'status' => $this->determineDeviceStatus($positionData),
|
|
'last_update' => $positionData['deviceTime'],
|
|
'position_id' => $position->id,
|
|
]);
|
|
}
|
|
}
|
|
}
|
|
|
|
private function determineDeviceStatus($positionData): string
|
|
{
|
|
$deviceTime = new \DateTime($positionData['deviceTime']);
|
|
$now = new \DateTime();
|
|
$diffMinutes = $now->diff($deviceTime)->i + ($now->diff($deviceTime)->h * 60);
|
|
|
|
if ($diffMinutes <= 5) {
|
|
return 'online';
|
|
} elseif ($diffMinutes <= 30) {
|
|
return 'offline';
|
|
} else {
|
|
return 'unknown';
|
|
}
|
|
}
|
|
|
|
public function render()
|
|
{
|
|
return view('livewire.dashboard');
|
|
}
|
|
}
|