gps_system/app/Services/TraccarService.php
sackey 6b878bb0a0
Some checks failed
linter / quality (push) Has been cancelled
tests / ci (push) Has been cancelled
Initial commit
2025-09-12 16:19:56 +00:00

386 lines
9.7 KiB
PHP

<?php
namespace App\Services;
use GuzzleHttp\Client;
use GuzzleHttp\Cookie\CookieJar;
use GuzzleHttp\Exception\GuzzleException;
use Illuminate\Support\Facades\Log;
use Illuminate\Support\Facades\Cache;
class TraccarService
{
private Client $client;
private string $baseUrl;
private string $username;
private string $password;
public function __construct()
{
$this->baseUrl = config('services.traccar.api_url');
$this->username = config('services.traccar.admin_username');
$this->password = config('services.traccar.admin_password');
$this->client = new Client([
'timeout' => 30,
'headers' => [
'Accept' => 'application/json',
'User-Agent' => 'Laravel-TraccarService/1.0',
],
'verify' => false, // For development only
]);
}
/**
* Make authenticated request to Traccar API
*/
private function makeRequest(string $method, string $endpoint, array $data = []): array
{
try {
$fullUrl = $this->baseUrl . $endpoint;
$options = [
'auth' => [$this->username, $this->password, 'basic'],
'headers' => [
'Accept' => 'application/json',
'User-Agent' => 'Laravel-TraccarService/1.0',
],
];
if (!empty($data)) {
$options['json'] = $data;
$options['headers']['Content-Type'] = 'application/json';
}
$response = $this->client->request($method, $fullUrl, $options);
$responseBody = $response->getBody()->getContents();
$result = json_decode($responseBody, true);
Log::info("Traccar API Request", [
'method' => $method,
'endpoint' => $endpoint,
'full_url' => $fullUrl,
'status' => $response->getStatusCode(),
'response_length' => strlen($responseBody),
'response_preview' => substr($responseBody, 0, 200),
'content_type' => $response->getHeaderLine('Content-Type'),
]);
// Handle empty responses or null JSON decode results
if ($result === null && !empty($responseBody)) {
Log::warning("Failed to decode JSON response", [
'raw_response' => $responseBody,
'content_type' => $response->getHeaderLine('Content-Type'),
]);
return [];
}
return $result ?? [];
} catch (GuzzleException $e) {
Log::error("Traccar API Error", [
'method' => $method,
'endpoint' => $endpoint,
'full_url' => $this->baseUrl . $endpoint,
'error' => $e->getMessage(),
]);
throw $e;
}
}
// ===== SERVER METHODS =====
/**
* Get server information
*/
public function getServerInfo(): array
{
return $this->makeRequest('GET', '/server');
}
// ===== USER METHODS =====
/**
* Get all users
*/
public function getUsers(): array
{
return $this->makeRequest('GET', '/users');
}
/**
* Create a new user in Traccar
*/
public function createUser(array $userData): array
{
return $this->makeRequest('POST', '/users', $userData);
}
/**
* Update user in Traccar
*/
public function updateUser(int $userId, array $userData): array
{
return $this->makeRequest('PUT', "/users/{$userId}", $userData);
}
/**
* Delete user from Traccar
*/
public function deleteUser(int $userId): bool
{
$this->makeRequest('DELETE', "/users/{$userId}");
return true;
}
// ===== DEVICE METHODS =====
/**
* Get all devices
*/
public function getDevices(?int $userId = null): array
{
$endpoint = '/devices';
if ($userId) {
$endpoint .= "?userId={$userId}";
}
return $this->makeRequest('GET', $endpoint);
}
/**
* Create a new device
*/
public function createDevice(array $deviceData): array
{
return $this->makeRequest('POST', '/devices', $deviceData);
}
/**
* Update device
*/
public function updateDevice(int $deviceId, array $deviceData): array
{
return $this->makeRequest('PUT', "/devices/{$deviceId}", $deviceData);
}
/**
* Delete device
*/
public function deleteDevice(int $deviceId): bool
{
$this->makeRequest('DELETE', "/devices/{$deviceId}");
return true;
}
// ===== POSITION METHODS =====
/**
* Get latest positions for all devices
*/
public function getPositions(): array
{
return $this->makeRequest('GET', '/positions');
}
/**
* Get latest positions for specific devices
*/
public function getDevicePositions(int $deviceId, ?string $from = null, ?string $to = null): array
{
$params = ['deviceId' => $deviceId];
if ($from) $params['from'] = $from;
if ($to) $params['to'] = $to;
$query = http_build_query($params);
$endpoint = "/positions?{$query}";
return $this->makeRequest('GET', $endpoint);
}
/**
* Get latest positions for multiple devices
*/
public function getMultipleDevicePositions(array $deviceIds): array
{
if (empty($deviceIds)) {
return [];
}
// Build query string for multiple device IDs
$params = [];
foreach ($deviceIds as $deviceId) {
$params[] = "deviceId={$deviceId}";
}
$query = implode('&', $params);
$endpoint = "/positions?{$query}";
return $this->makeRequest('GET', $endpoint);
}
/**
* Get real-time positions (latest for all user devices)
*/
public function getRealTimePositions(array $deviceIds = []): array
{
if (empty($deviceIds)) {
// Get latest positions for all devices
return $this->getPositions();
}
// Get positions for specific devices
return $this->getMultipleDevicePositions($deviceIds);
}
// ===== GEOFENCE METHODS =====
/**
* Get all geofences
*/
public function getGeofences(): array
{
return $this->makeRequest('GET', '/geofences');
}
/**
* Create geofence
*/
public function createGeofence(array $geofenceData): array
{
return $this->makeRequest('POST', '/geofences', $geofenceData);
}
/**
* Update geofence
*/
public function updateGeofence(int $geofenceId, array $geofenceData): array
{
return $this->makeRequest('PUT', "/geofences/{$geofenceId}", $geofenceData);
}
/**
* Delete geofence
*/
public function deleteGeofence(int $geofenceId): bool
{
$this->makeRequest('DELETE', "/geofences/{$geofenceId}");
return true;
}
// ===== EVENT METHODS =====
/**
* Get events
*/
public function getEvents(?int $deviceId = null, ?string $type = null): array
{
$params = [];
if ($deviceId) $params['deviceId'] = $deviceId;
if ($type) $params['type'] = $type;
$query = http_build_query($params);
$endpoint = '/events' . ($query ? "?{$query}" : '');
return $this->makeRequest('GET', $endpoint);
}
// ===== REPORT METHODS =====
/**
* Get trip reports
*/
public function getTripReports(array $deviceIds, string $from, string $to): array
{
$params = [
'deviceId' => $deviceIds,
'from' => $from,
'to' => $to
];
$query = http_build_query($params);
return $this->makeRequest('GET', "/reports/trips?{$query}");
}
/**
* Get summary reports
*/
public function getSummaryReports(array $deviceIds, string $from, string $to): array
{
$params = [
'deviceId' => $deviceIds,
'from' => $from,
'to' => $to
];
$query = http_build_query($params);
return $this->makeRequest('GET', "/reports/summary?{$query}");
}
// ===== COMMAND METHODS =====
/**
* Send command to device
*/
public function sendCommand(array $commandData): array
{
return $this->makeRequest('POST', '/commands/send', $commandData);
}
/**
* Get available command types
*/
public function getCommandTypes(): array
{
return $this->makeRequest('GET', '/commands/types');
}
// ===== PERMISSION METHODS =====
/**
* Link user to device
*/
public function linkUserDevice(int $userId, int $deviceId): bool
{
$this->makeRequest('POST', '/permissions', [
'userId' => $userId,
'deviceId' => $deviceId
]);
return true;
}
/**
* Unlink user from device
*/
public function unlinkUserDevice(int $userId, int $deviceId): bool
{
$this->makeRequest('DELETE', '/permissions', [
'userId' => $userId,
'deviceId' => $deviceId
]);
return true;
}
// ===== UTILITY METHODS =====
/**
* Test API connection
*/
public function testConnection(): bool
{
try {
$this->getServerInfo();
return true;
} catch (\Exception $e) {
return false;
}
}
/**
* Clear cached data
*/
public function clearCache(): void
{
Cache::forget('traccar_positions');
}
}