sayliR #48
@@ -11,6 +11,7 @@ use Illuminate\Container\Attributes\DB;
|
||||
use Illuminate\Http\Request;
|
||||
use Illuminate\Support\Facades\DB as FacadesDB;
|
||||
use Illuminate\Support\Facades\Http;
|
||||
use Illuminate\Support\Facades\Log;
|
||||
use Illuminate\Support\Facades\Validator;
|
||||
|
||||
class TelemetryController extends Controller
|
||||
@@ -26,119 +27,80 @@ class TelemetryController extends Controller
|
||||
|
||||
public function telemetryDataAsset(Request $request)
|
||||
{
|
||||
try {
|
||||
// Read and validate token first
|
||||
$token = readHeaderToken();
|
||||
if (!$token) {
|
||||
return response()->json([
|
||||
'success' => false,
|
||||
'error' => 'Authorization token required'
|
||||
], 401);
|
||||
}
|
||||
$validator = Validator::make($request->all(), [
|
||||
'asset_id' => 'required|string',
|
||||
'startTs' => 'nullable|string',
|
||||
'endTs' => 'nullable|string',
|
||||
]);
|
||||
|
||||
$validator = Validator::make($request->all(), [
|
||||
'asset_id' => 'required|string',
|
||||
'startTs' => 'nullable|string',
|
||||
'endTs' => 'nullable|string',
|
||||
]);
|
||||
if ($validator->fails()) {
|
||||
return jsonResponseWithErrorMessage($validator->errors()->first(), 400);
|
||||
}
|
||||
|
||||
if ($validator->fails()) {
|
||||
return response()->json([
|
||||
'success' => false,
|
||||
'error' => $validator->errors()->first()
|
||||
], 400);
|
||||
}
|
||||
$assetId = $request->input('asset_id');
|
||||
$startTs = $request->input('startTs') ?: null;
|
||||
$endTs = $request->input('endTs') ?: null;
|
||||
|
||||
$assetId = $request->input('asset_id');
|
||||
$startTs = $request->input('startTs');
|
||||
$endTs = $request->input('endTs');
|
||||
|
||||
// Get devices with their profiles and timeseries keys
|
||||
$devices = Device::with(['deviceProfile', 'timeseriesKeys' => function($query) {
|
||||
$query->where('display_on_dashboard', true)
|
||||
->orWhere('display_on_popup', true)
|
||||
->select(['key_name', 'display_name', 'display_on_dashboard', 'display_on_popup', 'device_profile_xid']);
|
||||
}])
|
||||
// Fetch devices associated with the asset
|
||||
$devices = Device::with('deviceProfile')
|
||||
->where('asset_id', $assetId)
|
||||
->get();
|
||||
|
||||
if ($devices->isEmpty()) {
|
||||
return response()->json([
|
||||
'success' => false,
|
||||
'error' => 'No devices found for the asset'
|
||||
], 404);
|
||||
}
|
||||
if ($devices->isEmpty()) {
|
||||
return response()->json(['error' => 'No devices found for the asset'], 404);
|
||||
}
|
||||
|
||||
// Prepare data for bulk telemetry request
|
||||
$deviceIds = $devices->pluck('id');
|
||||
$allKeyNames = TimeseriesKeyMaster::whereIn('device_profile_xid', $devices->pluck('device_profile_id'))
|
||||
->where(function($query) {
|
||||
$response = [];
|
||||
|
||||
foreach ($devices as $device) {
|
||||
$telemetry = [];
|
||||
|
||||
// Fetch key names and additional columns from TimeseriesKeyMaster
|
||||
$keysData = TimeseriesKeyMaster::where('device_profile_xid', $device->device_profile_id)
|
||||
->where(function ($query) {
|
||||
$query->where('display_on_dashboard', true)
|
||||
->orWhere('display_on_popup', true);
|
||||
->orWhere('display_on_popup', true);
|
||||
})
|
||||
->pluck('key_name')
|
||||
->unique()
|
||||
->toArray();
|
||||
->get(['key_name', 'display_name', 'display_on_dashboard', 'display_on_popup']);
|
||||
|
||||
// Get telemetry data with token
|
||||
$bulkTelemetry = $this->customerInfoService->getTelemetryData(
|
||||
$deviceIds,
|
||||
$allKeyNames,
|
||||
$startTs,
|
||||
$endTs,
|
||||
$token // Pass the token to the service
|
||||
);
|
||||
$keyNames = $keysData->pluck('key_name')->toArray();
|
||||
|
||||
if (!is_array($bulkTelemetry)) {
|
||||
throw new \Exception("Invalid telemetry data format received from service");
|
||||
}
|
||||
// Log key names for debugging
|
||||
// Log::info('Key Names for Device', ['device_id' => $device->id, 'key_names' => $keyNames]);
|
||||
|
||||
// Format the response
|
||||
$response = $devices->map(function($device) use ($bulkTelemetry) {
|
||||
$telemetry = collect();
|
||||
// Fetch telemetry data
|
||||
$telemetryResponse = $this->customerInfoService->getTelemetryData($device, $keyNames, $startTs, $endTs);
|
||||
|
||||
foreach ($device->timeseriesKeys as $keyData) {
|
||||
$keyName = $keyData->key_name;
|
||||
foreach ($keysData as $keyData) {
|
||||
$keyName = $keyData->key_name;
|
||||
|
||||
if (isset($bulkTelemetry[$device->id][$keyName])) {
|
||||
$telemetry = $telemetry->merge(
|
||||
collect($bulkTelemetry[$device->id][$keyName])->map(function($item) use ($keyData) {
|
||||
return [
|
||||
'key_name' => $keyData->key_name,
|
||||
'display_name' => $keyData->display_name,
|
||||
'display_on_dashboard' => $keyData->display_on_dashboard,
|
||||
'display_on_popup' => $keyData->display_on_popup,
|
||||
'timestamp' => $item['ts'] ?? null,
|
||||
'value' => $item['value'] ?? null,
|
||||
];
|
||||
})
|
||||
);
|
||||
if (isset($telemetryResponse[$keyName])) {
|
||||
foreach ($telemetryResponse[$keyName] as $item) {
|
||||
$telemetry[] = [
|
||||
'key_name' => $keyName,
|
||||
'display_name' => $keyData->display_name,
|
||||
'display_on_dashboard' => $keyData->display_on_dashboard,
|
||||
'display_on_popup' => $keyData->display_on_popup,
|
||||
'timestamp' => $item['ts'] ?? null,
|
||||
'value' => $item['value'] ?? null,
|
||||
];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return [
|
||||
'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->values()->all(),
|
||||
];
|
||||
});
|
||||
|
||||
return response()->json([
|
||||
'success' => true,
|
||||
'telemetry' => $response
|
||||
]);
|
||||
|
||||
} catch (\Exception $e) {
|
||||
return response()->json([
|
||||
'success' => false,
|
||||
'error' => 'Failed to fetch telemetry data',
|
||||
'details' => config('app.debug') ? $e->getMessage() : null
|
||||
], 500);
|
||||
$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' => $response]);
|
||||
}
|
||||
|
||||
|
||||
public function telemetryDataDevice(Request $request)
|
||||
{
|
||||
try {
|
||||
@@ -165,14 +127,16 @@ class TelemetryController extends Controller
|
||||
}
|
||||
|
||||
$deviceId = $request->input('device_id');
|
||||
$startTs = $request->input('startTs');
|
||||
$endTs = $request->input('endTs');
|
||||
$startTs = $request->input('startTs') ?: null;
|
||||
$endTs = $request->input('endTs') ?: null;
|
||||
|
||||
try {
|
||||
$deviceWithTelemetry = Device::with(['deviceProfile',
|
||||
'timeseriesKeys' => function($query) {
|
||||
$deviceWithTelemetry = Device::with([
|
||||
'deviceProfile',
|
||||
'timeseriesKeys' => function ($query) {
|
||||
$query->select('key_name', 'display_name', 'device_profile_xid');
|
||||
}])
|
||||
}
|
||||
])
|
||||
->where('id', $deviceId)
|
||||
->firstOrFail();
|
||||
|
||||
@@ -216,13 +180,11 @@ class TelemetryController extends Controller
|
||||
'telemetry_data' => $telemetry,
|
||||
]
|
||||
], 200);
|
||||
|
||||
} catch (\Illuminate\Database\Eloquent\ModelNotFoundException $e) {
|
||||
return response()->json([
|
||||
'success' => false,
|
||||
'error' => 'Device not found'
|
||||
], 404);
|
||||
|
||||
} catch (\Exception $e) {
|
||||
return response()->json([
|
||||
'success' => false,
|
||||
@@ -230,7 +192,6 @@ class TelemetryController extends Controller
|
||||
'details' => config('app.debug') ? $e->getMessage() : null
|
||||
], 503);
|
||||
}
|
||||
|
||||
} catch (\Exception $e) {
|
||||
return response()->json([
|
||||
'success' => false,
|
||||
@@ -361,4 +322,4 @@ class TelemetryController extends Controller
|
||||
// return response()->json(['telemetry' => $response]);
|
||||
// }
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@@ -10,7 +10,7 @@ use Illuminate\Support\Facades\Http;
|
||||
|
||||
use Illuminate\Http\Request;
|
||||
|
||||
class AlarmController extends Controller
|
||||
class AlarmControllerCommon extends Controller
|
||||
{
|
||||
protected $alarmService;
|
||||
|
||||
@@ -151,4 +151,35 @@ class AlarmController extends Controller
|
||||
}
|
||||
|
||||
|
||||
public function filterAlarm(Request $request)
|
||||
{
|
||||
try {
|
||||
$alarmData = $request->only([
|
||||
// 'statusList',
|
||||
'severity',
|
||||
// 'type',
|
||||
// 'assigneeId',
|
||||
'pageSize',
|
||||
'page',
|
||||
// 'textSearch',
|
||||
// 'sortProperty',
|
||||
// 'sortOrder',
|
||||
'startTs',
|
||||
'endTs'
|
||||
]);
|
||||
|
||||
$apiResponse = $this->alarmService->filterAlarm($alarmData);
|
||||
|
||||
return jsonResponseWithSuccessMessage('Alarm data retrieved successfully', ['api_response' => $apiResponse]);
|
||||
} catch (Exception $e) {
|
||||
Log::error("Error: " . $e->getMessage());
|
||||
|
||||
$errorResponse = json_decode($e->getMessage(), true);
|
||||
if (json_last_error() === JSON_ERROR_NONE) {
|
||||
return jsonResponseWithErrorMessage($errorResponse['message'] ?? 'Something went wrong', 400, $errorResponse);
|
||||
}
|
||||
|
||||
return jsonResponseWithErrorMessage($e->getMessage(), 500);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -8,6 +8,9 @@ use Illuminate\Support\Facades\Log;
|
||||
use App\Services\AdminService;
|
||||
use Exception;
|
||||
use Illuminate\Support\Facades\Request;
|
||||
use Illuminate\Support\Facades\Cache;
|
||||
use Carbon\Carbon;
|
||||
|
||||
|
||||
class AlarmService
|
||||
{
|
||||
@@ -16,8 +19,44 @@ class AlarmService
|
||||
public function __construct(AdminService $adminService)
|
||||
{
|
||||
$this->adminService = $adminService;
|
||||
$this->baseUrl = env('THINGSBOARD_URL', 'http://65.0.131.117:8080');
|
||||
$this->username = env('THINGSBOARD_USERNAME', 'tenant1@thingsboard.org');
|
||||
$this->password = env('THINGSBOARD_PASSWORD', 'tenant1');
|
||||
}
|
||||
|
||||
private $baseUrl;
|
||||
private $username;
|
||||
private $password;
|
||||
|
||||
|
||||
|
||||
public function getToken()
|
||||
{
|
||||
if (Cache::has('thingsboard_token')) {
|
||||
return Cache::get('thingsboard_token');
|
||||
}
|
||||
|
||||
$response = Http::withHeaders([
|
||||
'accept' => 'application/json',
|
||||
'Content-Type' => 'application/json',
|
||||
])
|
||||
->post("{$this->baseUrl}/api/auth/login", [
|
||||
'username' => $this->username,
|
||||
'password' => $this->password,
|
||||
]);
|
||||
|
||||
|
||||
if ($response->successful()) {
|
||||
$token = $response->json('token');
|
||||
Cache::put('thingsboard_token', $token, now()->addMinutes(15));
|
||||
return $token;
|
||||
} else {
|
||||
Log::error("ThingsBoard Authentication Failed: " . $response->body());
|
||||
throw new Exception('Unable to authenticate with ThingsBoard: ' . $response->body());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public function getAdminAlarm($data)
|
||||
{
|
||||
try {
|
||||
@@ -214,6 +253,8 @@ class AlarmService
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
public function getTelemetryData($device, $keyNames, $startTs, $endTs)
|
||||
{
|
||||
$token = $this->adminService->getToken();
|
||||
@@ -307,6 +348,62 @@ class AlarmService
|
||||
return $response->json();
|
||||
}
|
||||
|
||||
public function createOrUpdateAlarm(array $data)
|
||||
{
|
||||
|
||||
$token = $this->getToken();
|
||||
|
||||
$payload = [
|
||||
'type' => $data['type'] ?? null,
|
||||
'severity' => $data['severity'] ?? null,
|
||||
'acknowledged' => $data['acknowledged'] ?? null,
|
||||
'cleared' => $data['cleared'] ?? Carbon::now()->timestamp,
|
||||
'startTs' => $data['startTs'] ?? Carbon::now()->timestamp,
|
||||
'endTs' => $data['endTs'] ?? Carbon::now()->timestamp,
|
||||
'originator' => [
|
||||
'id' => $data['originator'] ?? null,
|
||||
'entityType' => 'DEVICE'
|
||||
],
|
||||
'assigneeId' => [
|
||||
'id' => $data['assigneeId'] ?? null,
|
||||
'entityType' => 'USER'
|
||||
],
|
||||
'details' => $data['details'] ?? [],
|
||||
'propagate' => $data['propagate'] ?? false,
|
||||
'propagateToOwner' => $data['propagateToOwner'] ?? false,
|
||||
|
||||
];
|
||||
|
||||
|
||||
// Optional fields
|
||||
if (!empty($data['id'])) {
|
||||
$payload['id'] = [
|
||||
'id' => $data['id'],
|
||||
'entityType' => 'ALARM'
|
||||
];
|
||||
}
|
||||
|
||||
|
||||
|
||||
$url = "{$this->baseUrl}/api/alarm";
|
||||
$method = 'post';
|
||||
|
||||
$response = Http::withHeaders([
|
||||
'Authorization' => "Bearer $token",
|
||||
'Accept' => 'application/json',
|
||||
'Content-Type' => 'application/json',
|
||||
])->post($url, $payload);
|
||||
|
||||
if (!$response->successful()) {
|
||||
Log::error("API Error Response:", ['body' => $response->body()]);
|
||||
throw new Exception('API Error: ' . $response->body());
|
||||
}
|
||||
|
||||
$apiResponse = $response->json();
|
||||
|
||||
return $apiResponse;
|
||||
}
|
||||
|
||||
|
||||
// public function deleteDevice(array $data)
|
||||
// {
|
||||
|
||||
@@ -54,7 +54,7 @@ class CustomerInfoService
|
||||
|
||||
|
||||
|
||||
public function getTelemetryData($device, $keyNames, $startTs, $endTs)
|
||||
public function getTelemetryData($device, $keyNames, $startTs , $endTs )
|
||||
{
|
||||
$token = $this->adminService->getToken();
|
||||
|
||||
@@ -68,15 +68,16 @@ public function getTelemetryData($device, $keyNames, $startTs, $endTs)
|
||||
|
||||
$keys = implode(',', $keyNames);
|
||||
|
||||
// Build query parameters dynamically
|
||||
$queryParams = [
|
||||
'keys' => $keys,
|
||||
];
|
||||
|
||||
if (!empty($startTs)) {
|
||||
if ($startTs) {
|
||||
$queryParams['startTs'] = $startTs;
|
||||
}
|
||||
|
||||
if (!empty($endTs)) {
|
||||
if ($endTs) {
|
||||
$queryParams['interval'] = $endTs;
|
||||
}
|
||||
|
||||
@@ -99,7 +100,7 @@ public function getTelemetryData($device, $keyNames, $startTs, $endTs)
|
||||
|
||||
// Decode the telemetry response
|
||||
$telemetry = $response->json();
|
||||
// Log::info("Telemetry Data", $telemetry);
|
||||
Log::info("Telemetry Data", $telemetry);
|
||||
|
||||
if (json_last_error() !== JSON_ERROR_NONE) {
|
||||
Log::error("Failed to decode telemetry response for device: {$device->name}", [
|
||||
@@ -128,19 +129,23 @@ public function getTelemetryData($device, $keyNames, $startTs, $endTs)
|
||||
$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/58bf81a0-0619-11f0-a9dc-45dd276e4cd5/values/timeseries", [
|
||||
])->get("$baseUrl/api/plugins/telemetry/DEVICE/{$deviceId}/values/timeseries", [
|
||||
'Accept' => 'application/json',
|
||||
])->get("$baseUrl/api/plugins/telemetry/DEVICE/{$deviceId}/values/timeseries", $queryParams);
|
||||
|
||||
'keys' => $keys,
|
||||
'startTs' => $startTs,
|
||||
'interval' => $endTs,
|
||||
'limit' => 100,
|
||||
'useStrictDataTypes' => false
|
||||
]);
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -3,7 +3,8 @@
|
||||
// use App\Http\Controllers\AssetController;
|
||||
|
||||
use App\Http\Controllers\APIS\AdminApi\AlarmController;
|
||||
use App\Http\Controllers\APIS\CustomerApi\CustomerController;
|
||||
use App\Http\Controllers\AlarmControllerCommon;
|
||||
use App\Http\Controllers\APIS\AdminApi\CustomerController;
|
||||
use App\Http\Controllers\APIS\AdminApi\UsersController;
|
||||
use App\Http\Controllers\APIS\AdminApi\DeviceController;
|
||||
use Illuminate\Http\Request;
|
||||
@@ -48,6 +49,7 @@ Route::post('/users-customer-list', [UsersController::class, 'userlistCustomer']
|
||||
|
||||
|
||||
|
||||
|
||||
//******************************************************* Device API********************************************************
|
||||
Route::post('/device/create-or-update', [DeviceController::class, 'createOrUpdateDevice'])->name('device.create-or-update');
|
||||
Route::get('/device/list', [DeviceController::class, 'listDevices'])->name('device.list');
|
||||
@@ -61,6 +63,7 @@ Route::post('/update-device-profile-master/{deviceId}', [DeviceProfileMasterCont
|
||||
|
||||
|
||||
//******************************************************* Alarm API ********************************************************
|
||||
Route::post('/alarm/create-or-update', [AlarmController::class, 'createOrUpdateAlarm'])->name('alarm.create-or-update');
|
||||
Route::get('/alarm/{id}', [AlarmController::class, 'getAlarmById'])->name('get.alarm');
|
||||
Route::post('/alarm/ack/{id}', [AlarmController::class, 'acknowledgeAlarmById'])->name('ack.alarm');
|
||||
Route::post('/alarm/create-or-update', [AlarmControllerCommon::class, 'createOrUpdateAlarm'])->name('alarm.create-or-update');
|
||||
Route::get('/alarm/{id}', [AlarmControllerCommon::class, 'getAlarmById'])->name('get.alarm');
|
||||
Route::post('/alarm/ack/{id}', [AlarmControllerCommon::class, 'acknowledgeAlarmById'])->name('ack.alarm');
|
||||
Route::post('/alarm/filter', [AlarmControllerCommon::class, 'filterAlarm'])->name('alarm.filter');
|
||||
|
||||
Reference in New Issue
Block a user