diff --git a/app/Http/Controllers/APIS/CustomerApi/TelemetryController.php b/app/Http/Controllers/APIS/CustomerApi/TelemetryController.php index b5dbeb3..b4e3672 100644 --- a/app/Http/Controllers/APIS/CustomerApi/TelemetryController.php +++ b/app/Http/Controllers/APIS/CustomerApi/TelemetryController.php @@ -5,8 +5,11 @@ namespace App\Http\Controllers\APIS\CustomerApi; use App\Http\Controllers\Controller; use App\Models\Asset; use App\Models\Device; +use App\Models\TimeseriesKeyMaster; use App\Services\CustomerInfoService; +use Illuminate\Container\Attributes\DB; use Illuminate\Http\Request; +use Illuminate\Support\Facades\DB as FacadesDB; use Illuminate\Support\Facades\Http; class TelemetryController extends Controller @@ -18,10 +21,14 @@ class TelemetryController extends Controller $this->customerInfoService = $customerInfoService; } + + + + public function telemetryData($assetId) { - // Fetch devices with asset and telemetry keys + device profile - $devices = Device::with(['asset', 'timeseriesKeys.deviceProfile']) + // ✅ Fetch devices with profiles + $devices = Device::with('deviceProfile') ->where('asset_id', $assetId) ->get(); @@ -29,31 +36,54 @@ class TelemetryController extends Controller return response()->json(['error' => 'No devices found for the asset'], 404); } - $telemetryData = []; - - // Set start and end timestamps $startTs = now()->subHours(1)->timestamp * 1000; $endTs = now()->timestamp * 1000; - // Fetch telemetry data from ThingsBoard - $thingsBoardData = $this->customerInfoService->getTelemetryData($devices, $startTs, $endTs); + $response = []; foreach ($devices as $device) { - $deviceToken = $device->token; // Use token + $telemetry = []; - // Find telemetry data by token - $telemetry = collect($thingsBoardData) - ->firstWhere('device_token', $deviceToken); + // ✅ Fetch key names from timeseries_key_master associated with the device profile + $keyNames = TimeseriesKeyMaster::where('device_profile_xid', $device->device_profile_id) + ->pluck('key_name') + ->toArray(); - $telemetryData[] = [ - 'device_name' => $device->name, - 'telemetry' => $telemetry['telemetry'] ?? [], - ]; + // ✅ Fetch telemetry data + $telemetryResponse = $this->customerInfoService->getTelemetryData($device, $keyNames, $startTs, $endTs); + + + foreach ($keyNames as $keyName) { + if (isset($telemetryResponse[$keyName])) { + foreach ($telemetryResponse[$keyName] as $item) { + $telemetry[] = [ + 'key_name' => $keyName, + 'timestamp' => $item['ts'] ?? null, + 'value' => $item['value'] ?? null + ]; + } + } + } + + if (!empty($telemetry)) { + $response[] = [ + 'device_id' => (string) $device->id, + 'device_profile_name' => (string) $device->deviceProfile->name, + 'asset_id' => (string) $device->asset_id, + 'device_profile_id' => (string) $device->device_profile_id, + 'telemetry' => $telemetry, + ]; + } } - return response()->json([ - 'telemetry' => $telemetryData - ]); + return response()->json(['telemetry' => $response]); } + + + + + + + } diff --git a/app/Models/Device.php b/app/Models/Device.php index 6e6734c..83171bb 100644 --- a/app/Models/Device.php +++ b/app/Models/Device.php @@ -11,13 +11,16 @@ class Device extends Model protected $table = 'devices'; + // Ensure UUIDs are treated as strings + protected $keyType = 'string'; // Treat ID as a string + public $incrementing = false; // Disable auto-incrementing + protected $fillable = [ 'id', 'name', 'asset_id', 'type', 'device_profile_id', - 'asset_id', 'tenant_id', 'customer_id', 'label', @@ -27,6 +30,14 @@ class Device extends Model 'device_data', ]; + // Cast UUIDs and related IDs as strings + protected $casts = [ + 'id' => 'string', + 'asset_id' => 'string', + 'device_profile_id' => 'string' + ]; + + // Relationships public function asset() { return $this->belongsTo(Asset::class, 'asset_id', 'id'); diff --git a/app/Models/DeviceProfileMaster.php b/app/Models/DeviceProfileMaster.php index d7ff059..3addc04 100644 --- a/app/Models/DeviceProfileMaster.php +++ b/app/Models/DeviceProfileMaster.php @@ -11,12 +11,21 @@ class DeviceProfileMaster extends Model protected $table = 'device_profile_master'; + protected $keyType = 'string'; // Treat ID as a string + public $incrementing = false; // Disable auto-incrementing + protected $fillable = [ 'id', 'name', 'description', ]; + protected $casts = [ + 'id' => 'string', + + ]; + + public function devices() { return $this->hasMany(Device::class, 'device_profile_id', 'id'); @@ -26,4 +35,4 @@ class DeviceProfileMaster extends Model { return $this->hasMany(TimeseriesKeyMaster::class, 'device_profile_xid', 'id'); } -} \ No newline at end of file +} diff --git a/app/Services/CustomerInfoService.php b/app/Services/CustomerInfoService.php index cdd447c..3aad87d 100644 --- a/app/Services/CustomerInfoService.php +++ b/app/Services/CustomerInfoService.php @@ -45,89 +45,236 @@ class CustomerInfoService } } + // public function getTelemetryData($devices, $startTs, $endTs, $limit = 100) + // { + // try { + // // Get ThingsBoard token from AdminService + // $token = $this->adminService->getToken(); - public function getTelemetryData($devices, $startTs, $endTs, $limit = 100) + // if (!$token) { + // Log::error("Failed to authenticate with ThingsBoard."); + // return ['error' => 'Authentication failed']; + // } + + // $baseUrl = env('THINGSBOARD_URL', 'http://65.0.131.117:8080'); + // $telemetryData = []; + + // foreach ($devices as $device) { + // $deviceToken = $device->token; + + // // Include asset_id, device_profile_id, and device name + // $assetId = $device->asset_id; + // $deviceProfileId = $device->device_profile_id; + // $deviceName = $device->name; + + // if (!$deviceToken) { + // Log::warning("Device token missing for device: {$deviceName} (ID: {$device->id})"); + // continue; + // } + + // $keys = $device->timeseriesKeys->pluck('key_name')->implode(','); + + // if (empty($keys)) { + // Log::warning("No telemetry keys found for device: {$deviceName} (Token: {$deviceToken})"); + // continue; + // } + + // // Make the telemetry API call + // $response = Http::withHeaders([ + // 'X-Authorization' => "Bearer $token", + // 'Accept' => 'application/json', + // ])->get("{$baseUrl}/api/plugins/telemetry/DEVICE/{$deviceToken}/values/timeseries", [ + // 'keys' => $keys, + // 'startTs' => $startTs, + // 'endTs' => $endTs, + // 'limit' => $limit, + // 'useStrictDataTypes' => 'false', + // ]); + + // if (!$response->successful()) { + // Log::error("Failed to fetch telemetry for device: {$deviceName} (Token: {$deviceToken})"); + // continue; + // } + + // $data = $response->json(); + + // // Format telemetry data with asset_id, device_profile_id, and name as key + // $formattedTelemetry = []; + + // if (!empty($data)) { + // foreach ($data as $key => $values) { + // foreach ($values as $item) { + // $formattedTelemetry[] = [ + // 'key' => $key, + // 'value' => $item['value'], + // 'ts' => $item['ts'] + // ]; + // } + // } + // } + + // $telemetryData[] = [ + // 'asset_id' => $assetId, + // 'device_profile_id' => $deviceProfileId, + // 'name' => $deviceName, + // 'telemetry' => $formattedTelemetry, + // ]; + // } + + // return $telemetryData; + + // } catch (\Exception $e) { + // Log::error("Error fetching telemetry data: " . $e->getMessage()); + // return ['error' => 'Failed to fetch telemetry data']; + // } + // } + + // public function getTelemetryData($devices, $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'); + + // $headers = [ + // 'Authorization: Bearer ' . $token, + // 'accept: application/json' + // ]; + + // $allTelemetry = []; + + // foreach ($devices as $device) { + // $deviceId = $device->id; + // $keys = $device->timeseriesKeys->pluck('key_name')->filter()->implode(','); + + // if (empty($keys)) { + // Log::warning("No telemetry keys found for device: {$device->name}"); + // $allTelemetry[$deviceId] = [ + // 'status' => 'error', + // 'message' => 'No telemetry keys found' + // ]; + // continue; + // } + + // $url = "$baseUrl/api/plugins/telemetry/DEVICE/{$deviceId}/values/timeseries" + // . "?keys={$keys}&startTs={$startTs}&endTs={$endTs}&limit=100"; + + // $ch = curl_init($url); + // curl_setopt($ch, CURLOPT_RETURNTRANSFER, true); + // curl_setopt($ch, CURLOPT_HTTPHEADER, $headers); + + // $response = curl_exec($ch); + // $httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE); + // $error = curl_error($ch); + // curl_close($ch); + + // if ($error || $httpCode !== 200) { + // Log::error("Failed to fetch telemetry for device: {$device->name} (ID: {$deviceId})", [ + // 'http_code' => $httpCode, + // 'error' => $error, + // 'url' => $url, + // 'response' => $response + // ]); + + // $allTelemetry[$deviceId] = [ + // 'status' => 'error', + // 'message' => "Failed to fetch telemetry. HTTP Code: $httpCode, Error: $error" + // ]; + // continue; + // } + + // $telemetry = json_decode($response, true); + + // if (json_last_error() !== JSON_ERROR_NONE) { + // Log::error("Failed to decode telemetry response for device: {$device->name}", [ + // 'response' => $response + // ]); + + // $allTelemetry[$deviceId] = [ + // 'status' => 'error', + // 'message' => 'Invalid telemetry response format' + // ]; + // continue; + // } + + // $allTelemetry[$deviceId] = [ + // 'status' => 'success', + // 'telemetry' => $telemetry + // ]; + // } + + // return $allTelemetry; // Return telemetry data mapped by device_id + // } + + + + public function getTelemetryData($device, $keyNames, $startTs, $endTs) { - try { - // Get ThingsBoard token from AdminService - $token = $this->adminService->getToken(); + $token = $this->adminService->getToken(); - if (!$token) { - Log::error("Failed to authenticate with ThingsBoard."); - return ['error' => 'Authentication failed']; - } - - $baseUrl = env('THINGSBOARD_URL', 'http://65.0.131.117:8080'); - $telemetryData = []; - - foreach ($devices as $device) { - $deviceToken = $device->token; - - // Include asset_id, device_profile_id, and device name - $assetId = $device->asset_id; - $deviceProfileId = $device->device_profile_id; - $deviceName = $device->name; - - if (!$deviceToken) { - Log::warning("Device token missing for device ID: {$device->id}"); - continue; - } - - $keys = $device->timeseriesKeys->pluck('key_name')->implode(','); - - if (empty($keys)) { - Log::warning("No telemetry keys found for device token: {$deviceToken}"); - continue; - } - - // Make the telemetry API call - $response = Http::withHeaders([ - 'X-Authorization' => "Bearer $token", - 'Accept' => 'application/json', - ])->get("{$baseUrl}/api/plugins/telemetry/DEVICE/{$deviceToken}/values/timeseries", [ - 'keys' => $keys, - 'startTs' => $startTs, - 'endTs' => $endTs, - 'limit' => $limit, - 'useStrictDataTypes' => 'false', - ]); - - if (!$response->successful()) { - Log::error("Failed to fetch telemetry data for device token: {$deviceToken}"); - continue; - } - - $data = $response->json(); - - // Format telemetry data with asset_id, device_profile_id, and name as key - $formattedTelemetry = []; - - foreach ($data as $key => $values) { - foreach ($values as $item) { - $formattedTelemetry[] = [ - 'key' => $key, - 'value' => $item['value'], - 'ts' => $item['ts'] - ]; - } - } - - $telemetryData[] = [ - 'asset_id' => $assetId, - 'device_profile_id' => $deviceProfileId, - 'name' => $deviceName, - 'telemetry' => $formattedTelemetry, - ]; - } - - return $telemetryData; - - } catch (Exception $e) { - Log::error("Error fetching telemetry data: " . $e->getMessage()); - return ['error' => 'Failed to fetch telemetry data']; + 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 + ]); + +// dd($response); + + // 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; } + + + + + + }