TelemetryData

This commit is contained in:
kshitige
2025-03-25 11:34:55 +05:30
parent c0e4fab684
commit cef3df82cf
4 changed files with 294 additions and 97 deletions

View File

@@ -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]);
}
}

View File

@@ -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');

View File

@@ -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');
}
}
}

View File

@@ -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;
}
}