adminService = $adminService; } // public function getThingsBoardDevices($customerId) // { // try { // $token = $this->adminService->getToken(); // if (!$token) { // Log::error("Failed to authenticate with ThingsBoard."); // return response()->json([ // 'error' => 'thingsboard_auth_failed', // 'message' => 'Failed to authenticate with ThingsBoard' // ], 401); // } // $response = Http::withHeaders([ // 'Authorization' => "Bearer $token", // 'Accept' => 'application/json', // ])->get("http://65.0.131.117:8080/api/customer/{$customerId}/deviceInfos?pageSize=100&page=0"); // if (!$response->successful()) { // Log::error("Failed to fetch ThingsBoard devices: " . $response->body()); // return response()->json([ // 'error' => 'thingsboard_fetch_failed', // 'message' => 'Failed to fetch devices from ThingsBoard', // 'details' => $response->body() // ], $response->status()); // } // $data = $response->json(); // return $data['data'] ?? []; // } catch (\Exception $e) { // Log::error("Error fetching ThingsBoard devices: " . $e->getMessage()); // return response()->json([ // 'error' => 'thingsboard_error', // 'message' => 'Error fetching devices from ThingsBoard', // 'details' => $e->getMessage() // ], 500); // } // } public function getTelemetryData($device, $keyNames, $startTs, $endTs) { $token = $this->adminService->getToken(); if (!$token) { return ['error' => 'Failed to fetch ThingsBoard token']; } $baseUrl = env('THINGSBOARD_URL'); $deviceId = $device->id; $keys = implode(',', $keyNames); // Build query parameters dynamically $queryParams = [ 'keys' => $keys, ]; if ($startTs) { $queryParams['startTs'] = $startTs; } if ($endTs) { $queryParams['interval'] = $endTs; } // Make the HTTP request $response = Http::withHeaders([ 'Authorization' => "Bearer $token", 'Accept' => 'application/json', ])->get("{$baseUrl}api/plugins/telemetry/DEVICE/{$deviceId}/values/timeseries", $queryParams); // Check if the response was successful if (!$response->successful()) { Log::error("Failed to fetch telemetry for device: {$device->name} (ID: {$deviceId})", [ 'http_code' => $response->status(), 'url' => $response->effectiveUri(), 'response' => $response->body(), ]); return ['error' => "Failed to fetch telemetry. HTTP Code: " . $response->status()]; } // Decode the telemetry response $telemetry = $response->json(); Log::info("Telemetry Data", $telemetry); if (json_last_error() !== JSON_ERROR_NONE) { Log::error("Failed to decode telemetry response for device: {$device->name}", [ 'response' => $response->body(), ]); return ['error' => 'Invalid telemetry response format']; } return $telemetry; } public function getTelemetryDataDevice($device, $keyNames, $startTs, $endTs) { $token = $this->adminService->getToken(); if (!$token) { Log::error('Failed to fetch ThingsBoard token'); return ['error' => 'Failed to fetch ThingsBoard token']; } $baseUrl = env('THINGSBOARD_URL'); $deviceId = $device->id; $keys = implode(',', $keyNames); $queryParams = [ 'keys' => $keys, ]; if ($startTs) { $queryParams['startTs'] = $startTs; } if ($endTs) { $queryParams['endTs'] = $endTs; } $response = Http::withHeaders([ 'Authorization' => "Bearer $token", 'Accept' => 'application/json', ])->get("{$baseUrl}api/plugins/telemetry/DEVICE/{$deviceId}/values/timeseries", $queryParams); // Check if the response was successful if (!$response->successful()) { Log::error("Failed to fetch telemetry for device: {$device->name} (ID: {$deviceId})", [ 'http_code' => $response->status(), 'url' => $response->effectiveUri(), 'response' => $response->body() ]); return ['error' => "Failed to fetch telemetry. HTTP Code: " . $response->status()]; } // Decode the telemetry response $telemetry = $response->json(); if (json_last_error() !== JSON_ERROR_NONE) { Log::error("Failed to decode telemetry response for device: {$device->name}", [ 'response' => $response->body() ]); return ['error' => 'Invalid telemetry response format']; } return $telemetry; } public function getTelemetryDataDeviceDiagonostic($device, $keyNames, $startTs, $endTs) { $token = $this->adminService->getToken(); if (!$token) { Log::error('Failed to fetch ThingsBoard token'); return ['error' => 'Failed to fetch ThingsBoard token']; } $baseUrl = env('THINGSBOARD_URL'); $deviceId = $device->id; $keys = implode(',', $keyNames); $response = Http::withHeaders([ 'Authorization' => "Bearer $token", 'Accept' => 'application/json' // ])->get("$baseUrl/api/plugins/telemetry/DEVICE/58bf81a0-0619-11f0-a9dc-45dd276e4cd5/values/timeseries", [ ])->get("$baseUrl/api/plugins/telemetry/DEVICE/{$deviceId}/values/timeseries", [ 'keys' => $keys, // 'keys' => 'MechanicalHealth_valueInPercent', 'startTs' => $startTs, 'interval' => $endTs, 'limit' => 100, 'useStrictDataTypes' => false ]); // Check if the response was successful if (!$response->successful()) { Log::error("Failed to fetch telemetry for device: {$device->name} (ID: {$deviceId})", [ 'http_code' => $response->status(), 'url' => $response->effectiveUri(), 'response' => $response->body() ]); return ['error' => "Failed to fetch telemetry. HTTP Code: " . $response->status()]; } // Decode the telemetry response $telemetry = $response->json(); if (json_last_error() !== JSON_ERROR_NONE) { Log::error("Failed to decode telemetry response for device: {$device->name}", [ 'response' => $response->body() ]); return ['error' => 'Invalid telemetry response format']; } return $telemetry; } public function getCustomerDevicesAndAlarms($customerId) { $result = [ 'devices' => [], 'alarms' => [], 'errors' => [] ]; try { // Step 1: Get devices $devicesResponse = $this->getThingsBoardDevices($customerId); if (isset($devicesResponse['error'])) { $result['errors']['devices'] = $devicesResponse; } else { $result['devices'] = $devicesResponse; // Step 2: Get alarms if devices were fetched successfully $deviceIds = array_column($devicesResponse, 'id.id'); if (!empty($deviceIds)) { $alarmsResponse = $this->getDeviceAlarms($deviceIds); if (isset($alarmsResponse['error'])) { $result['errors']['alarms'] = $alarmsResponse; } else { $result['alarms'] = $alarmsResponse['data'] ?? []; } } } return $result; } catch (\Exception $e) { Log::error("ThingsBoard service error: " . $e->getMessage()); return [ 'error' => 'service_error', 'message' => 'Failed to complete ThingsBoard operation', 'details' => $e->getMessage() ]; } } /** * Get devices for a customer */ private function getThingsBoardDevices($customerId) { try { $token = $this->adminService->getToken(); if (!$token) { throw new \Exception("Failed to authenticate with ThingsBoard"); } $response = Http::withHeaders([ 'Authorization' => "Bearer $token", 'Accept' => 'application/json', ])->get("http://65.0.131.117:8080/api/customer/{$customerId}/deviceInfos?pageSize=100&page=0"); if (!$response->successful()) { throw new \Exception("Failed to fetch devices: " . $response->body()); } $data = $response->json(); return $data['data'] ?? []; } catch (\Exception $e) { Log::error("Device fetch error: " . $e->getMessage()); return [ 'error' => 'device_fetch_failed', 'message' => 'Failed to fetch devices', 'details' => $e->getMessage() ]; } } /** * Get alarms for specific devices (last 24 hours) */ private function getDeviceAlarms(array $deviceIds) { try { $token = $this->adminService->getToken(); if (!$token) { throw new \Exception("Failed to authenticate with ThingsBoard"); } $startTime = (time() - 86400) * 1000; // 24 hours ago in milliseconds $deviceIdsParam = implode(',', $deviceIds); $response = Http::withHeaders([ 'Authorization' => "Bearer $token", 'Accept' => 'application/json', ])->get("http://65.0.131.117:8080/api/v2/alarms", [ 'pageSize' => 100, 'page' => 0, 'startTime' => $startTime, 'deviceIds' => $deviceIdsParam ]); if (!$response->successful()) { throw new \Exception("Failed to fetch alarms: " . $response->body()); } return $response->json(); } catch (\Exception $e) { Log::error("Alarm fetch error: " . $e->getMessage()); return [ 'error' => 'alarm_fetch_failed', 'message' => 'Failed to fetch alarms', 'details' => $e->getMessage() ]; } } public function getToken() { $baseUrl = env('THINGSBOARD_URL', 'http://65.0.131.117:8080'); $username = env('THINGSBOARD_USERNAME', 'tenant1@thingsboard.org'); $password = env('THINGSBOARD_PASSWORD', 'tenant1'); if (Cache::has('thingsboard_token')) { return Cache::get('thingsboard_token'); } $response = Http::withHeaders([ // 'accept' => 'application/json', 'Content-Type' => 'application/json', ]) ->post("{$baseUrl}api/auth/login", [ 'username' => $username, 'password' => $password, ]); if ($response->successful()) { $token = $response->json('token'); Cache::put('thingsboard_token', $token, now()->addMinutes(1440)); return $token; } else { Log::error("ThingsBoard Authentication Failed: " . $response->body()); throw new Exception('Unable to authenticate with ThingsBoard: ' . $response->body()); } } public function fetchEntityQuery($deviceIds, $timeseriesKeys){ try{ $token = $this->adminService->getToken(); if (!$token) { throw new \Exception("Failed to authenticate with ThingsBoard"); } $url = env('THINGSBOARD_URL').'api/entitiesQuery/find'; $timeSeries = array_map(function($key) { return [ 'type' => 'TIME_SERIES', 'key' => $key ]; }, $timeseriesKeys); $payload = [ "entityFilter" => [ "type" => "entityList", "entityType" => "DEVICE", "entityList" => $deviceIds ], "pageLink" => [ "pageSize" => 100, "page" => 0, "textSearch" => "", "dynamic" => true ], "entityFields" => [ ["type" => "ENTITY_FIELD", "key" => "name"], ["type" => "ENTITY_FIELD", "key" => "type"], ], "latestValues" => $timeSeries ]; $response = Http::withHeaders([ 'accept' => 'application/json', 'Content-Type' => 'application/json', 'X-Authorization' => 'Bearer ' . $token, ])->post($url, $payload); // Return JSON response return response()->json($response->json(), $response->status()); } catch(Exception $e){ return response()->json(['success' => false, 'message' => $e->getMessage()], 500); } } public function fetchTelemetryData($deviceId,$keys,$ts=[]) { $url = env('THINGSBOARD_URL') ."api/plugins/telemetry/DEVICE/{$deviceId}/values/timeseries?useStrictDataTypes=false"; $token = $this->adminService->getToken(); if (!$token) { throw new \Exception("Failed to authenticate with ThingsBoard"); } try { $response = Http::withToken($token)->asForm()->get($url, [ 'keys' => $keys, 'startTs' => $ts['startTs'] ?? null, 'endTs' => $ts['endTs'] ?? null, 'limit' => 250 ]); if ($response->successful()) { return $response->json(); } else { return response()->json([ 'success' => false, 'message' => 'Failed to fetch data', 'status' => $response->status(), ], $response->status()); } } catch (\Exception $e) { return response()->json([ 'success' => false, 'message' => 'An error occurred: ' . $e->getMessage(), ], 500); } } public function getDevicesCount($deviceIds) { try { $token = $this->adminService->getToken(); if (!$token) { throw new \Exception("Failed to authenticate with ThingsBoard"); } $url = env('THINGSBOARD_URL') . 'api/entitiesQuery/find'; $payload = [ "entityFilter" => [ "type" => "entityList", "entityType" => "DEVICE", "entityList" => $deviceIds ], "keyFilters" => [ [ "key" => [ "type" => "ATTRIBUTE", "key" => "active" ], "valueType" => "BOOLEAN", "predicate" => [ "operation" => "EQUAL", "value" => [ "defaultValue" => true, "dynamicValue" => null ], "type" => "BOOLEAN" ] ] ], "pageLink" => [ "pageSize" => 100, "page" => 0, "sortOrder" => [ "key" => [ "type" => "ENTITY_FIELD", "key" => "name" ], "direction" => "ASC" ] ] ]; $response = Http::withHeaders([ 'accept' => 'application/json', 'Content-Type' => 'application/json', 'X-Authorization' => 'Bearer ' . $token, ])->post($url, $payload); if ($response->successful()) { $data = $response->json(); return [ 'totalDevices' => count($deviceIds), 'activeDevices' => count($data['data'] ?? []) ]; } return [ 'totalDevices' => count($deviceIds), 'activeDevices' => 0 ]; } catch (\Exception $e) { Log::error('Failed to get devices count: ' . $e->getMessage()); return [ 'totalDevices' => count($deviceIds), 'activeDevices' => 0 ]; } } public function getActiveDevicesList($deviceIds){ try { $token = $this->adminService->getToken(); if (!$token) { throw new \Exception("Failed to authenticate with ThingsBoard"); } $url = env('THINGSBOARD_URL') . 'api/entitiesQuery/find'; $payload = [ "entityFilter" => [ "type" => "entityList", "entityType" => "DEVICE", "entityList" => $deviceIds ], "keyFilters" => [ [ "key" => [ "type" => "ATTRIBUTE", "key" => "active" ], "valueType" => "BOOLEAN", "predicate" => [ "operation" => "EQUAL", "value" => [ "defaultValue" => true, "dynamicValue" => null ], "type" => "BOOLEAN" ] ] ], "pageLink" => [ "pageSize" => 100, "page" => 0, "sortOrder" => [ "key" => [ "type" => "ENTITY_FIELD", "key" => "name" ], "direction" => "ASC" ] ] ]; $response = Http::withHeaders([ 'accept' => 'application/json', 'Content-Type' => 'application/json', 'X-Authorization' => 'Bearer ' . $token, ])->post($url, $payload); // if (!$response->successful()) { // throw new \Exception("Failed to fetch active devices: " . $response->body()); // } $activeDevices = $response->json(); return [ 'activeDevices' => $activeDevices['data'] ?? [], 'totalElements' => $activeDevices['totalElements'] ?? 0 ]; } catch(Exception $e){ return response()->json(['success' => false, 'message' => $e->getMessage()], 500); } } public function fetchDeviceAlarms(array $deviceIds, $data=[]) { try { $token = $this->adminService->getToken(); if (!$token) { throw new \Exception("Failed to authenticate with ThingsBoard"); } $url = env('THINGSBOARD_URL') . 'api/alarmsQuery/find'; if (isset($data['startTs']) && isset($data['endTs'])) { $startDate = \DateTime::createFromFormat('d/m/Y', $data['startTs']); $endDate = \DateTime::createFromFormat('d/m/Y', $data['endTs']); if ($startDate && $endDate) { $startTimestamp = $startDate->getTimestamp() * 1000; $endTimestamp = $endDate->getTimestamp() * 1000; } } // Timestamp range (modify as needed) $startTs = $startTimestamp ?? now()->subHours(24)->timestamp * 1000; $endTs = $endTimestamp ?? now()->timestamp * 1000; $entityList = $data['deviceIds'] ?? $deviceIds; // dd($entityList); $payload = [ "entityFilter" => [ "type" => "entityList", "entityType" => "DEVICE", "entityList" => $entityList ], "pageLink" => [ // "startTs" => $startTs, // "endTs" => $endTs, "pageSize" => 100, "page" => 0, "textSearch" => "", "statusList" => $data['statusList'] ?? ['ACTIVE'], "severityList" => $data['severityList'] ?? [], "sortOrder" => [ "key" => [ "type" => "ALARM_FIELD", "key" => "createdTime" ], "direction" => "DESC" ] ], "alarmFields" => [] ]; $response = Http::withHeaders([ 'accept' => 'application/json', 'Content-Type' => 'application/json', 'X-Authorization' => 'Bearer ' . $token, ])->post($url, $payload); if (!$response->successful()) { throw new \Exception("Failed to fetch alarms: " . $response->body()); } $alarmData = $response->json(); return [ 'data' => $alarmData['data'] ?? [], 'count' => $alarmData['totalElements'] ?? 0 ]; } catch (\Exception $e) { return response()->json([ 'success' => false, 'message' => 'Error: ' . $e->getMessage() ], 500); } } }