Refactoring API's for Customer Dashboard
This commit is contained in:
@@ -6,6 +6,7 @@ use App\Http\Controllers\Controller;
|
||||
use App\Models\Asset;
|
||||
use App\Models\Customer;
|
||||
use App\Models\Device;
|
||||
use App\Models\DeviceProfileMaster;
|
||||
use App\Models\TimeseriesAlertMessage;
|
||||
use App\Models\TimeseriesKeyMaster;
|
||||
use App\Models\User;
|
||||
@@ -13,12 +14,14 @@ use App\Models\UserAssetLink;
|
||||
use App\Services\AdminService;
|
||||
use App\Services\AlarmService;
|
||||
use App\Services\CustomerInfoService;
|
||||
use Exception;
|
||||
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;
|
||||
use Carbon\Carbon;
|
||||
|
||||
class TelemetryController extends Controller
|
||||
{
|
||||
@@ -33,7 +36,6 @@ class TelemetryController extends Controller
|
||||
$this->customerInfoService = $customerInfoService;
|
||||
$this->alarmService = $alarmService;
|
||||
$this->adminService = $adminService;
|
||||
|
||||
}
|
||||
|
||||
|
||||
@@ -837,4 +839,501 @@ class TelemetryController extends Controller
|
||||
// return response()->json(['telemetry' => $response]);
|
||||
// }
|
||||
|
||||
public function convertToUserTimezone($utcDatetime, $userTimezone = 'Asia/Kolkata', $format = 'd-M-Y H:i:s')
|
||||
{
|
||||
return Carbon::parse($utcDatetime, 'UTC')
|
||||
->setTimezone($userTimezone)
|
||||
->format($format);
|
||||
}
|
||||
|
||||
public function entityQuery(){
|
||||
try {
|
||||
$token = readHeaderToken();
|
||||
|
||||
// Retrieve devices of user
|
||||
$deviceIds = UserAssetLink::with('asset.devices')
|
||||
->where('user_id', $token['sub'])
|
||||
->get()
|
||||
->pluck('asset.devices')
|
||||
->flatten()
|
||||
->pluck('id')
|
||||
->toArray();
|
||||
|
||||
// Retrieve required timeseries of devices
|
||||
$timeseriesKeys = TimeseriesKeyMaster::where('display_on_dashboard', 1)
|
||||
->orWhere('display_on_popup',1)
|
||||
->get()
|
||||
->pluck('key_name')
|
||||
->flatten()
|
||||
->toArray();
|
||||
|
||||
$entityQuery = $this->customerInfoService->fetchEntityQuery($deviceIds, $timeseriesKeys);
|
||||
|
||||
// Ensure the response is converted to an array if it's a JsonResponse
|
||||
$data = $entityQuery instanceof \Illuminate\Http\JsonResponse ? $entityQuery->getData(true) : $entityQuery;
|
||||
|
||||
$timeseriesKeyMap = TimeseriesKeyMaster::where('display_on_dashboard', 1)
|
||||
->orWhere('display_on_popup', 1)
|
||||
->get()
|
||||
->groupBy('device_profile_xid')
|
||||
->map(function ($group) {
|
||||
return $group->pluck('key_name')->toArray();
|
||||
});
|
||||
|
||||
// Process the array and format the output
|
||||
$formatted = [
|
||||
'success' => true,
|
||||
'data' => collect($data['data'])->map(function ($device) use ($timeseriesKeyMap) {
|
||||
$deviceType = $device['latest']['ENTITY_FIELD']['type']['value'] ?? null;
|
||||
$deviceProfileId = DeviceProfileMaster::where('name',$deviceType)->select('id')->first();
|
||||
$allTimeseries = $device['latest']['TIME_SERIES'] ?? [];
|
||||
|
||||
// Step 2: Get allowed keys for this device type
|
||||
$allowedKeys = $timeseriesKeyMap[$deviceProfileId['id']] ?? [];
|
||||
|
||||
// Step 3: Filter timeseries to only include allowed keys
|
||||
$filteredTimeseries = collect($allTimeseries)
|
||||
->only($allowedKeys)
|
||||
->toArray();
|
||||
|
||||
return [
|
||||
'deviceId' => $device['entityId']['id'] ?? null,
|
||||
'deviceName' => $device['latest']['ENTITY_FIELD']['name']['value'] ?? null,
|
||||
'deviceProfileId' => $deviceProfileId['id'] ?? null,
|
||||
'deviceType' => $deviceType,
|
||||
'timeseries' => $filteredTimeseries,
|
||||
];
|
||||
})->toArray()
|
||||
];
|
||||
|
||||
return response()->json($formatted);
|
||||
|
||||
} catch(Exception $e){
|
||||
return response()->json(['success' => false, 'message' => $e->getMessage()], 500);
|
||||
}
|
||||
}
|
||||
|
||||
public function getDeviceHealth(array $values): string
|
||||
{
|
||||
$hasRed = false;
|
||||
$hasOrange = false;
|
||||
|
||||
foreach ($values as $value) {
|
||||
if($value['key_name'] == 'PowerLoss_value'){
|
||||
if ($value['value'] > 5 && $value['value'] < 10) {
|
||||
$hasRed = true;
|
||||
break; // Red is highest priority, no need to continue
|
||||
} elseif ($value['value'] > 2.5 && $value['value'] < 5) {
|
||||
$hasOrange = true;
|
||||
}
|
||||
} else {
|
||||
if ($value['value'] > 0 && $value['value'] < 31) {
|
||||
$hasRed = true;
|
||||
break; // Red is highest priority, no need to continue
|
||||
} elseif ($value['value'] < 71) {
|
||||
$hasOrange = true;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
if ($hasRed) {
|
||||
return 'red';
|
||||
} elseif ($hasOrange) {
|
||||
return 'orange';
|
||||
}
|
||||
|
||||
return 'green';
|
||||
}
|
||||
|
||||
public function getAssetHealth($deviceHealthStatuses) {
|
||||
if (in_array('red', $deviceHealthStatuses)) {
|
||||
return 'red';
|
||||
} elseif (in_array('orange', $deviceHealthStatuses)) {
|
||||
return 'orange';
|
||||
}
|
||||
return 'green';
|
||||
}
|
||||
|
||||
public function userAssetsNew(){
|
||||
try {
|
||||
$token = readHeaderToken();
|
||||
|
||||
// Retrieve devices of user
|
||||
$assetDeviceListing = UserAssetLink::with('asset.devices')
|
||||
->where('user_id', $token['sub'])
|
||||
->get();
|
||||
|
||||
$formattedData = $assetDeviceListing->map(function ($link) {
|
||||
$asset = $link->asset;
|
||||
$deviceHealthStatuses = [];
|
||||
|
||||
$devicesData = $asset->devices->map(function ($device) use (&$deviceHealthStatuses) {
|
||||
|
||||
$timeseriesKeys = TimeseriesKeyMaster::where('display_on_health_condition', 1)
|
||||
->where('device_profile_xid', $device->device_profile_id)
|
||||
->pluck('key_name')
|
||||
->implode(',');
|
||||
|
||||
// \Log::info("Keys for device {$device->name}", [$timeseriesKeys]);
|
||||
|
||||
$telemetryValue = $this->customerInfoService->fetchTelemetryData($device->id, $timeseriesKeys);
|
||||
$data = $telemetryValue instanceof \Illuminate\Http\JsonResponse ? $telemetryValue->getData(true) : $telemetryValue;
|
||||
|
||||
// \Log::info("Telemetry data for device {$device->name}", $data);
|
||||
|
||||
$transformedTelemetry = [];
|
||||
// dd($data);
|
||||
if (!empty($data) && is_array($data)) {
|
||||
foreach ($data as $key => $items) {
|
||||
|
||||
foreach ($items as $item) {
|
||||
$transformedTelemetry[] = [
|
||||
'key_name' => $key,
|
||||
'value' => $item['value']
|
||||
];
|
||||
}
|
||||
}
|
||||
}
|
||||
// \Log::info("Transformed data for device {$device->name}", $transformedTelemetry);
|
||||
$deviceHealth = $this->getDeviceHealth($transformedTelemetry);
|
||||
$deviceHealthStatuses[] = $deviceHealth;
|
||||
|
||||
return [
|
||||
'deviceName' => $device->name,
|
||||
'deviceHealth' => $deviceHealth
|
||||
];
|
||||
})->values();
|
||||
|
||||
return [
|
||||
'assetName' => $asset->name,
|
||||
'assetHealth' => $this->getAssetHealth($deviceHealthStatuses),
|
||||
'devices' => $devicesData
|
||||
];
|
||||
|
||||
});
|
||||
|
||||
return response()->json(['success' => true,'data' => $formattedData]);
|
||||
|
||||
} catch(Exception $e){
|
||||
return response()->json(['success' => false, 'message' => $e->getMessage()], 500);
|
||||
}
|
||||
}
|
||||
public function customerDeviceInfoNew(){
|
||||
try {
|
||||
$token = readHeaderToken();
|
||||
|
||||
// Fetch all devices linked to user in one go
|
||||
$devices = UserAssetLink::with('asset.devices')
|
||||
->where('user_id', $token['sub'])
|
||||
->get()
|
||||
->pluck('asset.devices')
|
||||
->flatten()
|
||||
->unique('id'); // Ensure no duplicate devices
|
||||
|
||||
$good = $moderate = $bad = 0;
|
||||
$deviceIds = $devices->pluck('id')->toArray();
|
||||
|
||||
foreach ($deviceIds as $deviceId) {
|
||||
$device = Device::find($deviceId); // get the device row first
|
||||
|
||||
if ($device) {
|
||||
$timeseriesKeys = TimeseriesKeyMaster::where('display_on_health_condition', 1)
|
||||
->where('device_profile_xid', $device->device_profile_id)
|
||||
->pluck('key_name')
|
||||
->implode(',');
|
||||
|
||||
$telemetryValue = $this->customerInfoService->fetchTelemetryData($device->id, $timeseriesKeys);
|
||||
$data = $telemetryValue instanceof \Illuminate\Http\JsonResponse ? $telemetryValue->getData(true) : $telemetryValue;
|
||||
|
||||
$transformedTelemetry = [];
|
||||
|
||||
if (!empty($data) && is_array($data)) {
|
||||
foreach ($data as $key => $items) {
|
||||
|
||||
foreach ($items as $item) {
|
||||
$transformedTelemetry[] = [
|
||||
'key_name' => $key,
|
||||
'value' => $item['value']
|
||||
];
|
||||
}
|
||||
}
|
||||
}
|
||||
// \Log::info("Transformed data for device {$device->name}", $transformedTelemetry);
|
||||
$deviceHealth = $this->getDeviceHealth($transformedTelemetry);
|
||||
|
||||
match ($deviceHealth) {
|
||||
'green' => $good++,
|
||||
'orange' => $moderate++,
|
||||
default => $bad++
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
$deviceCount = $this->customerInfoService->getDevicesCount($deviceIds);
|
||||
$alarms = $this->customerInfoService->fetchDeviceAlarms($deviceIds);
|
||||
|
||||
$response = [
|
||||
'success' => true,
|
||||
'good' => $good,
|
||||
'moderate' => $moderate,
|
||||
'bad' => $bad,
|
||||
'total' => $deviceCount['totalDevices'],
|
||||
'active' => $deviceCount['activeDevices'],
|
||||
'alarm' => $alarms['count']
|
||||
];
|
||||
|
||||
return response()->json($response);
|
||||
|
||||
} catch(Exception $e){
|
||||
return response()->json(['success' => false, 'message' => $e->getMessage()], 500);
|
||||
}
|
||||
}
|
||||
|
||||
public function getDeviceIndicators($assetId){
|
||||
try{
|
||||
$token = readHeaderToken();
|
||||
|
||||
$assetDeviceListing = UserAssetLink::with('asset.devices')
|
||||
->where(['user_id' => $token['sub'], 'asset_id' => $assetId])
|
||||
->get();
|
||||
|
||||
$assetLink = $assetDeviceListing->map(function($link){
|
||||
$asset = $link->asset;
|
||||
$deviceData = $asset->devices->map(function($device){
|
||||
|
||||
$deviceProfile = Device::with('deviceProfile')
|
||||
->where('id', $device->id)
|
||||
->first();
|
||||
|
||||
$deviceProfileId = $deviceProfile?->deviceProfile?->id;
|
||||
$deviceProfileName = $deviceProfile?->deviceProfile?->name;
|
||||
|
||||
$timeseriesList = TimeseriesKeyMaster::where('display_on_dashboard', 1)
|
||||
->where('device_profile_xid', $deviceProfileId)
|
||||
->get(['key_name', 'display_name']);
|
||||
|
||||
$keyNameList = $timeseriesList->pluck('key_name')->implode(',');
|
||||
|
||||
$displayNameMap = $timeseriesList->pluck('display_name', 'key_name')->toArray();
|
||||
|
||||
$telemetryValue = $this->customerInfoService->fetchTelemetryData($device->id, $keyNameList);
|
||||
$data = $telemetryValue instanceof \Illuminate\Http\JsonResponse ? $telemetryValue->getData(true) : $telemetryValue;
|
||||
|
||||
$transformedTelemetry = [];
|
||||
|
||||
if (!empty($data) && is_array($data)) {
|
||||
foreach ($data as $key => $items) {
|
||||
|
||||
foreach ($items as $item) {
|
||||
$transformedTelemetry[] = [
|
||||
'display_name' => $displayNameMap[$key] ?? $key,
|
||||
'value' => $item['value']
|
||||
];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return [
|
||||
'deviceId' => $device->id,
|
||||
'deviceName' => $device->name,
|
||||
'deviceType' => $deviceProfileName,
|
||||
'indicator' => $transformedTelemetry
|
||||
];
|
||||
})->values();
|
||||
|
||||
return [
|
||||
'data' => $deviceData
|
||||
];
|
||||
|
||||
});
|
||||
|
||||
return response()->json($assetLink);
|
||||
|
||||
} catch(Exception $e){
|
||||
return response()->json(['success' => false, 'message' => $e->getMessage()], 500);
|
||||
}
|
||||
}
|
||||
|
||||
public function getAlerts($deviceId){
|
||||
try{
|
||||
$token = readHeaderToken();
|
||||
|
||||
$deviceParams = TimeseriesKeyMaster::select('key_name', 'display_name')
|
||||
->where('display_on_alerts', 1)
|
||||
->whereHas('device', function ($query) use ($deviceId) {
|
||||
$query->where('id', $deviceId);
|
||||
})
|
||||
->get();
|
||||
|
||||
$keyNameList = $deviceParams->pluck('key_name')->implode(',');
|
||||
$displayNameMap = $deviceParams->pluck('display_name', 'key_name')->toArray();
|
||||
|
||||
$telemetryValue = $this->customerInfoService->fetchTelemetryData($deviceId, $keyNameList);
|
||||
$data = $telemetryValue instanceof \Illuminate\Http\JsonResponse ? $telemetryValue->getData(true) : $telemetryValue;
|
||||
|
||||
$transformedTelemetry = [];
|
||||
|
||||
if (!empty($data) && is_array($data)) {
|
||||
foreach ($data as $key => $items) {
|
||||
|
||||
foreach ($items as $item) {
|
||||
|
||||
$timeseriesId = TimeseriesKeyMaster::where('display_name', $displayNameMap[$key])->first('id');
|
||||
|
||||
$fetchMsg = TimeseriesAlertMessage::where('timeseries_key_master_xid', $timeseriesId['id'])
|
||||
->where('min_value', '<=', $item['value'])
|
||||
->where('max_value', '>=', $item['value'])
|
||||
->first(['alert_msg']);
|
||||
|
||||
$alertPoints = [];
|
||||
|
||||
if (!empty($fetchMsg?->alert_msg)) {
|
||||
$alertPoints = explode("\n", trim($fetchMsg->alert_msg));
|
||||
}
|
||||
|
||||
$dateTime = Carbon::createFromTimestamp($item['ts'] / 1000)->format('d-M-Y H:i:s');
|
||||
|
||||
$transformedTelemetry[] = [
|
||||
'display_name' => $displayNameMap[$key] ?? $key,
|
||||
'alert_msg' => $alertPoints ?: ["No Alerts & Instructions"]
|
||||
];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return response()->json(
|
||||
[
|
||||
'updated_time' => $this->convertToUserTimezone($dateTime),
|
||||
'data' => $transformedTelemetry
|
||||
]
|
||||
);
|
||||
|
||||
} catch(Exception $e){
|
||||
return response()->json(['success' => false, 'message' => $e->getMessage()], 500);
|
||||
}
|
||||
}
|
||||
|
||||
public function getGlobalIndicators($deviceId){
|
||||
try{
|
||||
$token = readHeaderToken();
|
||||
|
||||
$deviceParams = TimeseriesKeyMaster::select('key_name', 'display_name')
|
||||
->where('display_on_popup', 1)
|
||||
->whereHas('device', function ($query) use ($deviceId) {
|
||||
$query->where('id', $deviceId);
|
||||
})
|
||||
->get();
|
||||
|
||||
$keyNameList = $deviceParams->pluck('key_name')->implode(',');
|
||||
$displayNameMap = $deviceParams->pluck('display_name', 'key_name')->toArray();
|
||||
|
||||
$telemetryValue = $this->customerInfoService->fetchTelemetryData($deviceId, $keyNameList);
|
||||
$data = $telemetryValue instanceof \Illuminate\Http\JsonResponse ? $telemetryValue->getData(true) : $telemetryValue;
|
||||
|
||||
$transformedTelemetry = [];
|
||||
|
||||
if (!empty($data) && is_array($data)) {
|
||||
foreach ($data as $key => $items) {
|
||||
|
||||
foreach ($items as $item) {
|
||||
|
||||
$dateTime = Carbon::createFromTimestamp($item['ts'] / 1000)->format('d-M-Y H:i:s');
|
||||
|
||||
switch (true) {
|
||||
case $item['value'] > 70:
|
||||
$status = 'Stable';
|
||||
break;
|
||||
|
||||
case $item['value'] > 30:
|
||||
$status = 'Attention';
|
||||
break;
|
||||
|
||||
default:
|
||||
$status = 'Alert';
|
||||
}
|
||||
|
||||
$transformedTelemetry[] = [
|
||||
'display_name' => $displayNameMap[$key] ?? $key,
|
||||
'value' => $item['value'],
|
||||
'health_status' => $status
|
||||
];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return response()->json(
|
||||
[
|
||||
'updated_time' => $this->convertToUserTimezone($dateTime),
|
||||
'data' => $transformedTelemetry
|
||||
]
|
||||
);
|
||||
|
||||
} catch(Exception $e){
|
||||
return response()->json(['success' => false, 'message' => $e->getMessage()], 500);
|
||||
}
|
||||
}
|
||||
|
||||
public function getTrends($deviceId){
|
||||
try {
|
||||
|
||||
$token = readHeaderToken();
|
||||
|
||||
$dates = collect(range(0, 6))->map(function ($i) {
|
||||
return Carbon::now()->subDays($i)->format('M d, Y');
|
||||
})->reverse()->values()->toArray();
|
||||
|
||||
foreach($dates as $date){
|
||||
$dateTs[] = (Carbon::createFromFormat('M d, Y', $date)->timestamp)*1000;
|
||||
// Start timestamp (beginning of the day)
|
||||
$ts['startTs'] = Carbon::createFromFormat('M d, Y', $date)->startOfDay()->timestamp * 1000;
|
||||
|
||||
// End timestamp (end of the day)
|
||||
$ts['endTs'] = Carbon::createFromFormat('M d, Y', $date)->endOfDay()->timestamp * 1000;
|
||||
|
||||
$deviceProfile = Device::with('deviceProfile')
|
||||
->where('id', $deviceId)
|
||||
->first();
|
||||
|
||||
$deviceProfileId = $deviceProfile?->deviceProfile?->id;
|
||||
|
||||
$parameters = parameters();
|
||||
$value1 = $value2 = [];
|
||||
|
||||
$telemetryValue1 = $this->customerInfoService->fetchTelemetryData($deviceId, $parameters[$deviceProfileId]['keyNameList1'], $ts);
|
||||
$trendsData1 = $telemetryValue1 instanceof \Illuminate\Http\JsonResponse ? $telemetryValue1->getData(true) : $telemetryValue1;
|
||||
|
||||
$telemetryValue2 = $this->customerInfoService->fetchTelemetryData($deviceId, $parameters[$deviceProfileId]['keyNameList2'], $ts);
|
||||
$trendsData2 = $telemetryValue2 instanceof \Illuminate\Http\JsonResponse ? $telemetryValue2->getData(true) : $telemetryValue2;
|
||||
|
||||
foreach ($trendsData1 as $key => $trend) {
|
||||
$displayName = TimeseriesKeyMaster::where('key_name',$key)->first('display_name');
|
||||
foreach ($trend as $val) {
|
||||
$value1[0][$displayName['display_name']][] = $val['value'];
|
||||
}
|
||||
}
|
||||
|
||||
foreach ($trendsData2 as $key => $trend) {
|
||||
$displayName = TimeseriesKeyMaster::where('key_name',$key)->first('display_name');
|
||||
foreach ($trend as $val) {
|
||||
$value2[0][$displayName['display_name']][] = $val['value'];
|
||||
}
|
||||
}
|
||||
|
||||
$graph1[$date] = $value1;
|
||||
$graph2[$date] = $value2;
|
||||
|
||||
}
|
||||
|
||||
return [
|
||||
'success' => true,
|
||||
'graph1' => $graph1,
|
||||
'graph2' => $graph2,
|
||||
];
|
||||
|
||||
} catch(Exception $e){
|
||||
return response()->json(['success' => false, 'message' => $e->getMessage()], 500);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
43
app/Http/Helpers/TrendKeysHelper.php
Normal file
43
app/Http/Helpers/TrendKeysHelper.php
Normal file
@@ -0,0 +1,43 @@
|
||||
<?php
|
||||
|
||||
function parameters()
|
||||
{
|
||||
|
||||
$keys = [
|
||||
"4e989080-04ad-11f0-a9dc-45dd276e4cd5" => [
|
||||
"keyNameList1" => 'PowerLoss_value,ChannelSpeed',
|
||||
"keyNameList2" => 'MechanicalHealth_valueInHealth,ChannelSpeed',
|
||||
],
|
||||
"88986090-16b3-11f0-a9dc-45dd276e4cd5" => [
|
||||
"keyNameList1" => 'PowerLoss_value,ChannelSpeed',
|
||||
"keyNameList2" => 'MechanicalHealth_valueInHealth,ChannelSpeed',
|
||||
],
|
||||
"a7802800-f34d-11ef-a9dc-45dd276e4cd5" => [
|
||||
"keyNameList1" => 'PowerLoss_value,ChannelSpeed',
|
||||
"keyNameList2" => 'MechanicalHealth_valueInHealth,ChannelSpeed',
|
||||
],
|
||||
"b82d42a0-f34d-11ef-a9dc-45dd276e4cd5" => [
|
||||
"keyNameList1" => 'GlobalMixed_valueInPercent,ChannelSpeed',
|
||||
"keyNameList2" => 'BearingGlobal_valueInPercent,ChannelSpeed',
|
||||
],
|
||||
"b60d08f0-16b3-11f0-a9dc-45dd276e4cd5" => [
|
||||
"keyNameList1" => 'GlobalMixed_valueInPercent,ChannelSpeed',
|
||||
"keyNameList2" => 'BearingGlobal_valueInPercent,ChannelSpeed',
|
||||
],
|
||||
"b13497a0-f34d-11ef-a9dc-45dd276e4cd5" => [
|
||||
"keyNameList1" => 'RegularityDeviation_valueInPercent,BladeStatus_valueInPercent,ChannelSpeed',
|
||||
"keyNameList2" => 'BearingStatus_valueInPercent,TurbineCoupling_valueInPercent,ChannelSpeed',
|
||||
],
|
||||
"72907b10-04ad-11f0-a9dc-45dd276e4cd5" => [
|
||||
"keyNameList1" => 'RegularityDeviation_valueInPercent,BladeStatus_valueInPercent,ChannelSpeed',
|
||||
"keyNameList2" => 'BearingStatus_valueInPercent,TurbineCoupling_valueInPercent,ChannelSpeed',
|
||||
],
|
||||
"bfbd2490-f34d-11ef-a9dc-45dd276e4cd5" => [
|
||||
"keyNameList1" => 'StaticTorque_value,ChannelSpeed',
|
||||
"keyNameList2" => 'StaticPower_value,ChannelSpeed',
|
||||
]
|
||||
];
|
||||
|
||||
return $keys;
|
||||
|
||||
}
|
||||
@@ -369,4 +369,48 @@ if (!function_exists('getTokenFromHeader')) {
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!function_exists('parameters')) {
|
||||
function parameters()
|
||||
{
|
||||
|
||||
$keys = [
|
||||
"4e989080-04ad-11f0-a9dc-45dd276e4cd5" => [
|
||||
"keyNameList1" => 'PowerLoss_value,ChannelSpeed',
|
||||
"keyNameList2" => 'MechanicalHealth_valueInHealth,ChannelSpeed',
|
||||
],
|
||||
"88986090-16b3-11f0-a9dc-45dd276e4cd5" => [
|
||||
"keyNameList1" => 'PowerLoss_value,ChannelSpeed',
|
||||
"keyNameList2" => 'MechanicalHealth_valueInHealth,ChannelSpeed',
|
||||
],
|
||||
"a7802800-f34d-11ef-a9dc-45dd276e4cd5" => [
|
||||
"keyNameList1" => 'PowerLoss_value,ChannelSpeed',
|
||||
"keyNameList2" => 'MechanicalHealth_valueInHealth,ChannelSpeed',
|
||||
],
|
||||
"b82d42a0-f34d-11ef-a9dc-45dd276e4cd5" => [
|
||||
"keyNameList1" => 'GlobalMixed_valueInPercent,ChannelSpeed',
|
||||
"keyNameList2" => 'BearingGlobal_valueInPercent,ChannelSpeed',
|
||||
],
|
||||
"b60d08f0-16b3-11f0-a9dc-45dd276e4cd5" => [
|
||||
"keyNameList1" => 'GlobalMixed_valueInPercent,ChannelSpeed',
|
||||
"keyNameList2" => 'BearingGlobal_valueInPercent,ChannelSpeed',
|
||||
],
|
||||
"b13497a0-f34d-11ef-a9dc-45dd276e4cd5" => [
|
||||
"keyNameList1" => 'RegularityDeviation_valueInPercent,BladeStatus_valueInPercent,ChannelSpeed',
|
||||
"keyNameList2" => 'BearingStatus_valueInPercent,TurbineCoupling_valueInPercent,ChannelSpeed',
|
||||
],
|
||||
"72907b10-04ad-11f0-a9dc-45dd276e4cd5" => [
|
||||
"keyNameList1" => 'RegularityDeviation_valueInPercent,BladeStatus_valueInPercent,ChannelSpeed',
|
||||
"keyNameList2" => 'BearingStatus_valueInPercent,TurbineCoupling_valueInPercent,ChannelSpeed',
|
||||
],
|
||||
"bfbd2490-f34d-11ef-a9dc-45dd276e4cd5" => [
|
||||
"keyNameList1" => 'StaticTorque_value,ChannelSpeed',
|
||||
"keyNameList2" => 'StaticPower_value,ChannelSpeed',
|
||||
]
|
||||
];
|
||||
|
||||
return $keys;
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@@ -53,6 +53,11 @@ class Asset extends Model
|
||||
return $this->belongsTo(Customer::class, 'customer_xid', 'id');
|
||||
}
|
||||
|
||||
public function userLinks()
|
||||
{
|
||||
return $this->hasMany(UserAssetLink::class, 'asset_id', 'id');
|
||||
}
|
||||
|
||||
public function devices()
|
||||
{
|
||||
return $this->hasMany(Device::class, 'asset_id', 'id');
|
||||
|
||||
@@ -33,12 +33,11 @@ class AdminService
|
||||
// 'accept' => 'application/json',
|
||||
'Content-Type' => 'application/json',
|
||||
])
|
||||
->post("{$this->baseUrl}/api/auth/login", [
|
||||
->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));
|
||||
|
||||
@@ -364,7 +364,6 @@ class CustomerInfoService
|
||||
$username = env('THINGSBOARD_USERNAME', 'tenant1@thingsboard.org');
|
||||
$password = env('THINGSBOARD_PASSWORD', 'tenant1');
|
||||
|
||||
|
||||
if (Cache::has('thingsboard_token')) {
|
||||
return Cache::get('thingsboard_token');
|
||||
}
|
||||
@@ -381,7 +380,7 @@ class CustomerInfoService
|
||||
|
||||
if ($response->successful()) {
|
||||
$token = $response->json('token');
|
||||
Cache::put('thingsboard_token', $token, now()->addMinutes(15));
|
||||
Cache::put('thingsboard_token', $token, now()->addMinutes(1440));
|
||||
return $token;
|
||||
} else {
|
||||
Log::error("ThingsBoard Authentication Failed: " . $response->body());
|
||||
@@ -389,4 +388,222 @@ class CustomerInfoService
|
||||
}
|
||||
}
|
||||
|
||||
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' => $ts ? 25000 : null
|
||||
]);
|
||||
|
||||
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/count';
|
||||
|
||||
// ---------- 1. Total count ----------
|
||||
$totalPayload = [
|
||||
"entityFilter" => [
|
||||
"type" => "entityList",
|
||||
"entityType" => "DEVICE",
|
||||
"entityList" => $deviceIds
|
||||
]
|
||||
];
|
||||
|
||||
$totalResponse = Http::withHeaders([
|
||||
'accept' => 'application/json',
|
||||
'Content-Type' => 'application/json',
|
||||
'X-Authorization' => 'Bearer ' . $token,
|
||||
])->post($url, $totalPayload);
|
||||
|
||||
$totalCount = $totalResponse->json() ?? 0;
|
||||
|
||||
// ---------- 2. active count (active = false) ----------
|
||||
$activePayload = [
|
||||
"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"
|
||||
]
|
||||
]
|
||||
]
|
||||
];
|
||||
|
||||
$activeResponse = Http::withHeaders([
|
||||
'accept' => 'application/json',
|
||||
'Content-Type' => 'application/json',
|
||||
'X-Authorization' => 'Bearer ' . $token,
|
||||
])->post($url, $activePayload);
|
||||
|
||||
$activeCount = $activeResponse->json() ?? 0;
|
||||
|
||||
// ---------- Return both counts ----------
|
||||
return [
|
||||
'totalDevices' => $totalCount,
|
||||
'activeDevices' => $activeCount
|
||||
];
|
||||
|
||||
|
||||
} catch(Exception $e){
|
||||
return response()->json(['success' => false, 'message' => $e->getMessage()], 500);
|
||||
}
|
||||
}
|
||||
|
||||
public function fetchDeviceAlarms(array $deviceIds)
|
||||
{
|
||||
try {
|
||||
$token = $this->adminService->getToken();
|
||||
if (!$token) {
|
||||
throw new \Exception("Failed to authenticate with ThingsBoard");
|
||||
}
|
||||
|
||||
$url = env('THINGSBOARD_URL') . 'api/alarmsQuery/find';
|
||||
|
||||
// Timestamp range (modify as needed)
|
||||
$startTs = now()->subDays(30)->timestamp * 1000;
|
||||
$endTs = now()->timestamp * 1000;
|
||||
|
||||
$payload = [
|
||||
"entityFilter" => [
|
||||
"type" => "entityList",
|
||||
"entityType" => "DEVICE",
|
||||
"entityList" => $deviceIds
|
||||
],
|
||||
"pageLink" => [
|
||||
"startTs" => $startTs,
|
||||
"endTs" => $endTs,
|
||||
"pageSize" => 100,
|
||||
"page" => 0,
|
||||
"textSearch" => "",
|
||||
"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);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
@@ -98,7 +98,7 @@ return [
|
||||
'users' => [
|
||||
'provider' => 'users',
|
||||
'table' => env('AUTH_PASSWORD_RESET_TOKEN_TABLE', 'password_reset_tokens'),
|
||||
'expire' => 60,
|
||||
'expire' => 1440,
|
||||
'throttle' => 60,
|
||||
],
|
||||
],
|
||||
|
||||
@@ -101,7 +101,7 @@ return [
|
||||
|
|
||||
*/
|
||||
|
||||
'ttl' => env('JWT_TTL', 60),
|
||||
'ttl' => env('JWT_TTL', 1440),
|
||||
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
|
||||
@@ -0,0 +1,28 @@
|
||||
<?php
|
||||
|
||||
use Illuminate\Database\Migrations\Migration;
|
||||
use Illuminate\Database\Schema\Blueprint;
|
||||
use Illuminate\Support\Facades\Schema;
|
||||
|
||||
return new class extends Migration
|
||||
{
|
||||
/**
|
||||
* Run the migrations.
|
||||
*/
|
||||
public function up(): void
|
||||
{
|
||||
Schema::table('timeseries_key_master', function (Blueprint $table) {
|
||||
$table->tinyInteger('display_on_health_condition')->default(0)->after('display_on_popup');
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Reverse the migrations.
|
||||
*/
|
||||
public function down(): void
|
||||
{
|
||||
Schema::table('timeseries_key_master', function (Blueprint $table) {
|
||||
$table->dropColumn('display_on_health_condition');
|
||||
});
|
||||
}
|
||||
};
|
||||
@@ -0,0 +1,28 @@
|
||||
<?php
|
||||
|
||||
use Illuminate\Database\Migrations\Migration;
|
||||
use Illuminate\Database\Schema\Blueprint;
|
||||
use Illuminate\Support\Facades\Schema;
|
||||
|
||||
return new class extends Migration
|
||||
{
|
||||
/**
|
||||
* Run the migrations.
|
||||
*/
|
||||
public function up(): void
|
||||
{
|
||||
Schema::table('timeseries_key_master', function (Blueprint $table) {
|
||||
$table->tinyInteger('display_on_alerts')->default(0)->after('display_on_health_condition');
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Reverse the migrations.
|
||||
*/
|
||||
public function down(): void
|
||||
{
|
||||
Schema::table('timeseries_key_master', function (Blueprint $table) {
|
||||
$table->dropColumn('display_on_alerts');
|
||||
});
|
||||
}
|
||||
};
|
||||
@@ -44,4 +44,15 @@ Route::middleware(['customerApiBasicAuth'])->group(function () {
|
||||
|
||||
Route::post('/alarm/filter', [AlarmControllerCommon::class, 'filterAlarm'])->name('alarm.filter');
|
||||
Route::post('/alarm', [AlarmControllerCommon::class, 'getDeviceAlarms'])->name('alarm.device');
|
||||
|
||||
// ***************************************** Based on Documentation ***********************************************
|
||||
|
||||
Route::get('/entity-query', [TelemetryController::class, 'entityQuery']);
|
||||
|
||||
Route::get('/user-assets-new', [TelemetryController::class, 'userAssetsNew']);
|
||||
Route::get('/customer-device-info-new', [TelemetryController::class, 'customerDeviceInfoNew']);
|
||||
Route::get('/get-device-indicators/{assetId}', [TelemetryController::class, 'getDeviceIndicators']);
|
||||
Route::get('/get-alerts/{deviceId}', [TelemetryController::class, 'getAlerts']);
|
||||
Route::get('/get-global-indicators/{deviceId}', [TelemetryController::class, 'getGlobalIndicators']);
|
||||
Route::get('/get-trends/{deviceId}', [TelemetryController::class, 'getTrends']);
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user