71 Commits

Author SHA1 Message Date
Shailesh-1981
60c15ede9e Merge branch 'main' of http://git.wdipl.com/Nikhil.Kadam/vib360 into shailesh 2025-05-27 19:22:44 +05:30
Shailesh-1981
fa8d4c1925 forget password 2025-05-27 19:22:36 +05:30
6e08276ad7 Merge branch 'main' of http://git.wdipl.com/Nikhil.Kadam/vib360 into nikhil 2025-05-27 19:06:42 +05:30
b307d87cbc Resolved issue in update asset and devices 2025-05-27 19:06:33 +05:30
1dd6126fbc Merge pull request 'shailesh' (#111) from shailesh into main
Reviewed-on: Nikhil.Kadam/vib360#111
2025-05-27 12:20:19 +00:00
Shailesh-1981
c5b9f011e4 Merge branch 'main' of http://git.wdipl.com/Nikhil.Kadam/vib360 into shailesh 2025-05-27 17:49:45 +05:30
Shailesh-1981
f3f2d87f37 code update route outside 2025-05-27 17:49:34 +05:30
2723692a69 Merge pull request 'api create forget password' (#110) from shailesh into main
Reviewed-on: Nikhil.Kadam/vib360#110
2025-05-27 11:57:15 +00:00
Shailesh-1981
6b7ce0e4bf api create forget password 2025-05-27 17:22:49 +05:30
85b86a00d9 Resolving issue in direct login api 2025-05-27 13:20:55 +05:30
Nikhil Kadam
6e6b09efae Adding multiple scenarios in graphs to display 2025-05-23 20:43:15 +05:30
Nikhil Kadam
e9d061b6ff Add graph parameters for Oil device 2025-05-23 17:33:44 +05:30
Nikhil Kadam
98d0b9acda Setting limit for OIL/Propeller 2025-05-23 16:11:20 +05:30
Nikhil Kadam
a42c124676 Changing threshold for propeller efficiency gauge 2025-05-23 14:23:45 +05:30
Nikhil Kadam
efc6b095ff Increasing upperlimit for Speed param 2025-05-23 12:19:37 +05:30
Nikhil Kadam
cc8934674c Cached for 60 seconds 2025-05-22 19:33:19 +05:30
Nikhil Kadam
1dcda12304 Cached device-indicator listing for 30 seconds 2025-05-22 18:40:21 +05:30
Nikhil Kadam
a974b9c906 Cached asset-device listing for 30 seconds 2025-05-22 18:36:45 +05:30
Nikhil Kadam
36a1679ab0 Device Indicators : Setting green default for Torque 2025-05-22 16:04:10 +05:30
Nikhil Kadam
84f86a3f81 Setting health status green for Torque by default 2025-05-22 14:54:32 +05:30
Nikhil Kadam
a17b525eee Fixing issue in threshold limit 2025-05-21 19:21:16 +05:30
Nikhil Kadam
2735a92512 New fields in create device and update asset/device 2025-05-21 18:16:45 +05:30
Nikhil Kadam
e4750c340d Changing device name with label 2025-05-21 15:02:00 +05:30
Nikhil Kadam
f8f7c791e3 Assigning asset to multiple users 2025-05-21 14:01:00 +05:30
Nikhil Kadam
5a935782f2 Setting d digit after decimal for device indicators 2025-05-21 12:59:00 +05:30
Nikhil Kadam
836f5d147e Creating api for live device list 2025-05-20 14:51:29 +05:30
Nikhil Kadam
558ff4535b Showing value for global 2025-05-20 12:27:21 +05:30
Nikhil Kadam
d5ec36d0b2 Show No Alerts & Instructions if no alerts from backend 2025-05-20 12:11:18 +05:30
Nikhil Kadam
2f64da4be9 Showing parameter status offine by checking device status 2025-05-19 19:00:27 +05:30
Nikhil Kadam
38a2c0586f Setting threshold value to Torsion(degree) 2025-05-19 17:45:47 +05:30
Nikhil Kadam
19498b04da Managing threshold values and status health 2025-05-19 13:16:38 +05:30
Nikhil Kadam
61bd2d75f0 Created user info api 2025-05-19 12:06:17 +05:30
Nikhil Kadam
621ccd51ca Making response consistent for user login 2025-05-18 19:09:34 +05:30
Nikhil Kadam
550b26349f Minor change to reflect previous commit 2025-05-18 18:24:52 +05:30
Nikhil Kadam
c4ee705ba0 Sending user name while in users_login api 2025-05-18 18:22:10 +05:30
Nikhil Kadam
d29f5f2825 Changed number format for global indicators 2025-05-18 14:07:40 +05:30
Nikhil Kadam
6efe85b631 Changed flow in user create api 2025-05-18 13:46:32 +05:30
Nikhil Kadam
4c7c7a5e9d Threshold limit changed for Torque parameters 2025-05-18 11:58:20 +05:30
Nikhil Kadam
3a560f6aa7 Resolving issue in create user api flow 2025-05-16 22:40:12 +05:30
Nikhil Kadam
f26dd03d2a Paramter changed for admin login api 2025-05-16 17:03:01 +05:30
Nikhil Kadam
d2c1ba578e Misfiring cylinder visible for gas engine 2025-05-16 15:16:10 +05:30
Nikhil Kadam
2cad19e740 Display count of device based on asset assigned to user 2025-05-16 11:39:39 +05:30
Nikhil Kadam
0852bcc680 Setting health status color for global indicators & fixing max value key 2025-05-16 11:30:06 +05:30
Nikhil Kadam
ce1203b5bb Removing cache & displaying list in desc in admin 2025-05-15 19:17:47 +05:30
Nikhil Kadam
040e3cc62d Setting threshold to Torque device 2025-05-15 15:28:59 +05:30
Nikhil Kadam
ef90e65066 Changing routes on baseUrl changed 2025-05-15 11:55:51 +05:30
Nikhil Kadam
42ebc1d71c User alarms based on user devices 2025-05-14 19:01:49 +05:30
Nikhil Kadam
327dcdf714 Create alarm issue fixed 2025-05-14 17:48:27 +05:30
Nikhil Kadam
32bf38b512 User alarms api 2025-05-14 17:30:40 +05:30
Nikhil Kadam
fefab7d5e7 Alarm api admin issue fixed 2025-05-14 16:22:58 +05:30
Nikhil Kadam
e9948e4430 Admin alarms 2025-05-14 16:00:50 +05:30
Nikhil Kadam
d0b4bcd930 Alarm api in progress 2025-05-13 17:11:47 +05:30
Nikhil Kadam
43bf2a4867 Display device type in live device api 2025-05-13 17:11:26 +05:30
Nikhil Kadam
f59c956e5d Setting flags for user & admin login 2025-05-13 13:19:27 +05:30
Nikhil Kadam
454534a8ac Code review and improving using agent 2025-05-12 20:11:07 +05:30
Nikhil Kadam
a28191a9bc Checking device belongs to user 2025-05-12 11:57:06 +05:30
Nikhil Kadam
a1949217b2 Changes in trends api 2025-05-08 20:05:26 +05:30
Nikhil Kadam
339ffc8b58 Fixing issue in Alarms api 2025-05-08 13:34:30 +05:30
Nikhil Kadam
02481b6dfa Developing api's for Cylinder specific & Peak pressure 2025-05-07 14:59:01 +05:30
Nikhil Kadam
537ccefcae Changing threshold values for global indicators 2025-05-06 15:47:30 +05:30
Nikhil Kadam
f92c056354 Setting threshold to global indicators 2025-05-06 13:50:58 +05:30
Nikhil Kadam
59a7eae635 Adding color code dynamically to device indicators 2025-05-06 12:05:24 +05:30
Nikhil Kadam
85bc0df3f6 Create user - activation mail link 2025-05-05 17:55:11 +05:30
Nikhil Kadam
258cee4c6d adding device-id in asset-device listing 2025-05-05 16:58:07 +05:30
Nikhil Kadam
cd62fae130 Fixing routing issues 2025-05-05 13:40:56 +05:30
Nikhil Kadam
fcd41d627c Adding assetId in asset-device listing 2025-05-05 12:20:02 +05:30
Nikhil Kadam
b75d2128f8 Indicators API - New column and value fluctuation 2025-05-02 21:05:40 +05:30
Nikhil Kadam
5b4eeff6d4 Error handling 2025-05-02 19:31:02 +05:30
Nikhil Kadam
beaa175d10 Merge branch 'main' of http://git.wdipl.com/Nikhil.Kadam/vib360 into nikhil 2025-05-02 12:39:01 +05:30
Nikhil Kadam
9e73a65c12 Route and response status changes 2025-05-02 12:38:30 +05:30
4680a193ae Merge pull request 'sneha' (#109) from sneha into main
Reviewed-on: Nikhil.Kadam/vib360#109
2025-05-02 06:26:54 +00:00
41 changed files with 2512 additions and 975 deletions

View File

@@ -46,7 +46,7 @@ class AdminDashboardController extends Controller
$response = Http::withHeaders([
'Authorization' => "Bearer $token",
'Accept' => 'application/json',
])->get("$baseUrl/api/device/info/{$deviceId}");
])->get("{$baseUrl}api/device/info/{$deviceId}");
if ($response->successful()) {
$deviceInfo = $response->json();
@@ -59,7 +59,7 @@ class AdminDashboardController extends Controller
$alarmsResponse = Http::withHeaders([
'Authorization' => "Bearer $token",
'Accept' => 'application/json',
])->get("$baseUrl/api/v2/alarms", [
])->get("{$baseUrl}api/v2/alarms", [
'pageSize' => 1000,
'page' => 0,
'status' => 'ACTIVE'

View File

@@ -79,15 +79,12 @@ class AssetadmintController extends Controller
// }
// }
public function storeAssest(CreateAssetRequest $request)
public function storeAssest(Request $request)
{
try {
// $additionalInfo = $request->has('additional_info') && is_string($request->additional_info)
// ? json_decode($request->additional_info, true)
// : $request->additional_info;
$assetData = [
'entity_type' => 'ASSET', // Backend defined
'createdTime' => now()->timestamp, // Backend defined
'entity_type' => 'ASSET',
'createdTime' => now()->timestamp,
'tenantId' => $request->tenant_id ?? Str::uuid()->toString(),
'customerId' => $request->customer_xid,
'name' => $request->name,
@@ -96,38 +93,76 @@ class AssetadmintController extends Controller
'assetProfileId' => $request->asset_profile_id ?? Str::uuid()->toString(),
'externalId' => $request->external_id ?? Str::uuid()->toString(),
'version' => $request->version ?? '1.0',
// 'additionalInfo' => $additionalInfo ?? ['description' => 'Default asset description'],
'additionalInfo' => $request->additionalInfo
];
$response = $this->adminService->createAsset($assetData);
if (!$response) {
throw new \Exception('Failed to create asset via admin service');
// Check if ID exists in request for update
if ($request->has('id')) {
$asset = Asset::find($request->id);
if (!$asset) {
throw new \Exception('Asset not found');
}
// Update asset via admin service
// $response = $this->adminService->updateAsset($request->id, $assetData);
// if (!$response) {
// throw new \Exception('Failed to update asset via admin service');
// }
// Update local database record
$asset->name = $assetData['name'];
$asset->type = $assetData['type'];
$asset->customer_xid = $assetData['customerId'];
$asset->label = $assetData['label'];
$asset->version = $assetData['version'];
$asset->additional_info = json_encode( $assetData['additionalInfo']);
$asset->save();
$message = 'Asset updated successfully!';
} else {
$assetNameExists = Asset::where('name', $request->name)->first();
if ($assetNameExists) {
return jsonResponseWithErrorMessage('Asset name already exists', 400);
}
// Create new asset via admin service
$response = $this->adminService->createAsset($assetData);
if (!$response) {
throw new \Exception('Failed to create asset via admin service');
}
// Create new local database record
$asset = new Asset();
$asset->id = $response['id']['id'] ?? Str::uuid()->toString();
$asset->entity_type = $assetData['entity_type'];
$asset->created_time = $assetData['createdTime'];
$asset->tenant_id = $assetData['tenantId'];
$asset->customer_xid = $assetData['customerId'];
$asset->name = $response['name'] ?? $assetData['name'];
$asset->type = $response['type'] ?? $assetData['type'];
$asset->label = $response['label'] ?? $assetData['label'];
$asset->asset_profile_id = $assetData['assetProfileId'];
$asset->external_id = $assetData['externalId'];
$asset->version = $response['version'] ?? $assetData['version'];
$asset->additional_info = json_encode($response['additionalInfo'] ?? $assetData['additionalInfo']);
$asset->save();
$message = 'Asset created successfully!';
}
$asset = new Asset();
$asset->id = $response['id']['id'] ?? Str::uuid()->toString();
$asset->entity_type = $assetData['entity_type']; // From backend
$asset->created_time = $assetData['createdTime']; // From backend
$asset->tenant_id = $assetData['tenantId'];
$asset->customer_xid = $assetData['customerId'];
$asset->name = $response['name'] ?? $assetData['name'];
$asset->type = $response['type'] ?? $assetData['type'];
$asset->label = $response['label'] ?? $assetData['label'];
$asset->asset_profile_id = $assetData['assetProfileId'];
$asset->external_id = $assetData['externalId'];
$asset->version = $response['version'] ?? $assetData['version'];
$asset->additional_info = json_encode($response['additionalInfo'] ?? $assetData['additionalInfo']);
// 'additional_info'  => json_encode($apiData['additionalInfo'] ?? []) 
$asset->save();
// Fetch only the customer name
// Fetch customer name
$customerName = \App\Models\Customer::where('id', $assetData['customerId'])->value('name');
return response()->json([
'message' => 'Asset created successfully!',
'message' => $message,
'data' => $asset,
'customer_name' => $customerName,
'api_response' => $response
// 'api_response' => $response
], 200);
} catch (\Exception $e) {
Log::error('Error in creating asset: ' . $e->getMessage());
Log::error('Error in asset operation: ' . $e->getMessage());
return response()->json(['error' => $e->getMessage()], 500);
}
}
@@ -236,7 +271,9 @@ class AssetadmintController extends Controller
$query->where('active', 1) // Only fetch active user asset links
->with(['user:id,first_name,last_name']); // Eager load user info
}
])->get()->map(function ($asset) {
])
->orderBy('created_at', 'desc')
->get()->map(function ($asset) {
$assetData = $asset->toArray();
unset($assetData['customer'], $assetData['user_asset_links']); // remove full objects
@@ -255,6 +292,7 @@ class AssetadmintController extends Controller
return null;
})->filter()->values(); // remove nulls and reset keys
// $assetData['assign_to_users'] = !empty($assignToUsers) ? implode(', ', $assignToUsers) : '';
$assetData['assign_to_users'] = $assignToUsers;
return $assetData;
@@ -440,31 +478,28 @@ class AssetadmintController extends Controller
$assetId = $request->asset_id;
$activeStatus = $request->active;
if ($activeStatus) {
// If assigning asset, first unassign from any other users
UserAssetLink::where('asset_id', $assetId)
->update(['active' => 0]);
// Now either update existing record or create a new one for this user and asset
if($userId){
foreach($userId as $user){
$userAssetLink = UserAssetLink::firstOrNew([
'user_id' => $user,
'asset_id' => $assetId
]);
$userAssetLink->active = $activeStatus;
$userAssetLink->save();
}
}
// Now either update existing record or create a new one for this user and asset
$userAssetLink = UserAssetLink::firstOrNew([
'user_id' => $userId,
'asset_id' => $assetId
]);
$userAssetLink->active = $activeStatus;
$userAssetLink->save();
$message = $activeStatus
? 'Asset assigned to user successfully.'
: 'Asset unassigned from user.';
? 'Asset assigned to user(s) successfully'
: 'Asset unassigned from user(s)';
Log::info($message, ['userId' => $userId, 'assetId' => $assetId]);
return response()->json([
'success' => true,
'message' => $message,
'data' => $userAssetLink
], 200);
} catch (Exception $e) {
Log::error("Error assigning/unassigning asset: " . $e->getMessage());
@@ -614,21 +649,21 @@ class AssetadmintController extends Controller
->get()
->map(function ($asset) {
// Since only active userAssetLinks are fetched, take the first one (only one user per asset)
$assignToUser = $asset->userAssetLinks->first(); // get first active link if exists
$userDetails = null;
if ($assignToUser && $assignToUser->user) {
$userDetails = [
'user_id' => $assignToUser->user->id,
'full_name' => trim($assignToUser->user->first_name . ' ' . $assignToUser->user->last_name),
];
}
$assignToUsers = $asset->userAssetLinks->map(function ($userAssetLink) {
$user = $userAssetLink->user;
if ($user) {
return [
'user_id' => $user->id,
'full_name' => trim($user->first_name . ' ' . $user->last_name),
];
}
});
return collect($asset)
->except('customer', 'userAssetLinks') // remove full objects
->except('customer', 'user_asset_links') // remove full objects
->merge([
'customer_name' => optional($asset->customer)->name,
'assign_to_user' => $userDetails, // assign only one user
'assign_to_users' => $assignToUsers, // attach user_id and full_name
]);
});

View File

@@ -125,7 +125,7 @@ class CustomerController extends Controller
public function listCustomers(Request $request)
{
try {
$customers = Customer::all();
$customers = Customer::orderBy('created_at', 'desc')->get();
return jsonResponseWithSuccessMessage('Customers fetched successfully', [
'customers' => $customers

View File

@@ -5,6 +5,7 @@ namespace App\Http\Controllers\APIS\AdminApi;
use App\Http\Controllers\Controller;
use App\Http\Requests\CreateDeviceRequest;
use App\Models\Device;
use App\Models\DeviceProfileMaster;
use App\Services\DeviceService;
use Illuminate\Http\Request;
use Illuminate\Support\Str;
@@ -25,11 +26,17 @@ class DeviceController extends Controller
}
public function createOrUpdateDevice(CreateDeviceRequest $request)
public function createOrUpdateDevice(Request $request)
{
try {
$deviceNameExists = Device::where('name', $request->name)->first();
if (empty($request->id) && $deviceNameExists) {
return jsonResponseWithErrorMessage('Device name already exists', 400);
}
$deviceData = [
'id' => $request->id ?? null,
'name' => $request->name ?? null,
'type' => $request->type ?? null,
'label' => $request->label ?? null,
@@ -53,9 +60,9 @@ class DeviceController extends Controller
// Optional Fields
// dd($request->id);
// Handle updating existing devices
if (!empty($request->id)) {
if (empty($request->id)) {
$deviceData['id'] = $request->id;
}
if (!empty($request->firmwareId)) {
@@ -67,33 +74,41 @@ class DeviceController extends Controller
// Call Service to create/update device
$apiResponse = $this->deviceService->createOrUpdateDevice($deviceData);
if (empty($request->id)) {
$apiResponse = $this->deviceService->createOrUpdateDevice($deviceData);
}
// Log::info("API Response: " . json_encode($apiResponse));
$deviceProfileName = DeviceProfileMaster::where('id', $request->deviceProfileId)->first();
// Store device in the database
$device = Device::updateOrCreate(
['id' => $apiResponse['id']['id'] ?? Str::uuid()->toString()],
['id' => $apiResponse['id']['id'] ?? $request->id],
[
'entity_type' => $apiResponse['id']['entityType'] ?? 'DEVICE',
'created_time' => $apiResponse['createdTime'] ?? now()->timestamp,
'customer_id' => $apiResponse['customerId']['id'] ?? null,
'name' => $apiResponse['name'] ?? null,
'type' => $apiResponse['type'] ?? null,
'label' => $apiResponse['label'] ?? null,
'asset_id' => $request->asset_id ?? 'null',
'device_profile_id' => $apiResponse['deviceProfileId']['id'] ?? null,
'firmware_id' => $apiResponse['firmwareId']['id'] ?? null,
'software_id' => $apiResponse['softwareId']['id'] ?? null,
'version' => $apiResponse['version'] ?? 1,
'tenant_id' => $apiResponse['tenantId']['id'] ?? null,
'device_data' => json_encode($apiResponse['deviceData'] ?? []),
'additional_info' => json_encode($apiResponse['additionalInfo'] ?? [])
'entity_type' => 'DEVICE',
'created_time' => now()->timestamp,
'customer_id' => $request->customerId ?? null,
'name' => $request->name ?? null,
'type' => $deviceProfileName['name'] ?? null,
'label' => $request->label ?? null,
'asset_id' => $request->asset_id ?? null,
'speed_limit' => $request->speed_limit ?? null,
'torque_limit' => $request->torque_limit ?? null,
'power_limit' => $request->power_limit ?? null,
'device_profile_id' => $request->deviceProfileId ?? null,
'firmware_id' => $request->firmware_id ?? null,
'software_id' => $request->software_id ?? null,
'version' => $request->version ?? 1,
'tenant_id' => $request->tenant_id ?? null,
'device_data' => json_encode($request->device_data ?? []),
'additional_info' => $request->additionalInfo
]
);
return jsonResponseWithSuccessMessage(
!empty($request->id) ? 'Device updated successfully' : 'Device created successfully',
['device' => $device, 'api_response' => $apiResponse]
['device' => $device]
);
} catch (Exception $e) {
Log::error("Error: " . $e->getMessage());
@@ -126,7 +141,7 @@ class DeviceController extends Controller
public function listDevices(Request $request)
{
try {
$devices = Device::with('deviceProfile', 'customer')->get()->map(function ($device) {
$devices = Device::with('deviceProfile', 'customer')->orderBy('created_at', 'desc')->get()->map(function ($device) {
$deviceData = $device->toArray();
unset($deviceData['device_profile'], $deviceData['customer']); // remove full relations

View File

@@ -17,7 +17,7 @@ class LoginController extends Controller
{
$validator = Validator::make($request->all(), [
'username' => 'required|string',
'email' => 'required|string',
'password' => 'required|string',
]);
if ($validator->fails()) {
@@ -32,15 +32,15 @@ class LoginController extends Controller
$response = Http::withHeaders([
'accept' => 'application/json',
'Content-Type' => 'application/json',
])->post("{$baseUrl}/api/auth/login", [
'username' => $request->username,
])->post("{$baseUrl}api/auth/login", [
'username' => $request->email,
'password' => $request->password,
]);
if ($response->successful()) {
$token = $response->json('token');
return jsonResponseWithSuccessMessage(__('Login successful'), $token, 200);
return jsonResponseWithSuccessMessage(__('Login successful'), $token, 1);
} else {
return response()->json([
'message' => __($response->json('message') ?? 'Invalid credentials')

View File

@@ -6,6 +6,7 @@ use App\Http\Controllers\Controller;
use Illuminate\Http\Request;
use App\Http\Requests\CreateUserRequest;
use App\Mail\Admin\UserCreatedMail;
use App\Mail\UserLink;
use App\Models\User;
use App\Services\AdminService;
use Exception;
@@ -19,6 +20,7 @@ use Illuminate\Support\Str;
use Illuminate\Validation\ValidationException;
use Illuminate\Support\Facades\Auth;
use Illuminate\Support\Facades\Validator;
use Tymon\JWTAuth\Facades\JWTAuth;
class UsersController extends Controller
{
@@ -256,7 +258,7 @@ class UsersController extends Controller
'default_dashboard_fullscreen' => $request->default_dashboard_fullscreen ?? false,
'home_dashboard_id' => $request->home_dashboard_id ?? null,
'home_dashboard_hide_toolbar' => $request->home_dashboard_hide_toolbar ?? false,
'user_credentials_enabled' => $request->user_credentials_enabled ?? false,
'user_credentials_enabled' => 0,
'failed_login_attempts' => $request->failed_login_attempts ?? 0,
'last_login_ts' => $request->last_login_ts,
'version' => $request->version ?? 0,
@@ -283,28 +285,30 @@ class UsersController extends Controller
'entityType' => 'CUSTOMER'
];
}
$serviceResponse = $this->adminService->createUser($serviceData);
if (isset($serviceResponse['error'])) {
$user->delete();
throw new \Exception($serviceResponse['message']);
}
// if (isset($serviceResponse['error'])) {
// $user->delete();
// throw new \Exception($serviceResponse['message']);
// }
$randomToken = Str::random(64);
$activationLink = url("/apia/activate/{$userId}?token={$randomToken}");
// $activationLink = url("/apia/activate/{$userId}?token={$randomToken}");
$newActivationLink = env('FRONTEND_URL') . "generate-password/{$userId}/{$randomToken}";
// Send activation email
Mail::to($user->email)->send(new UserCreatedMail($user, $activationLink));
$mail = Mail::to($user->email)->send(new UserCreatedMail($user, $newActivationLink));
return response()->json([
'success' => true,
'message' => 'User created successfully',
'data' => [
'user_id' => $userId,
'token'=>$randomToken,
'activation_link' => $activationLink,
'external_service_response' => $serviceResponse
'token' => $randomToken,
'activation_link' => $newActivationLink,
// 'external_service_response' => $serviceResponse
]
], 201);
} catch (QueryException $e) {
@@ -327,12 +331,13 @@ class UsersController extends Controller
public function list()
{
try {
$users = $this->adminService->listUsers();
$users = User::orderBy('created_at', 'desc')->get();
if (!empty($users['data'])) {
if (!empty($users)) {
return response()->json([
'message' => 'Users fetched successfully',
'users' => $users['data']
'count' => $users->count(),
'users' => $users
], 200);
}
@@ -477,9 +482,8 @@ class UsersController extends Controller
// }
public function activate(Request $request, $id)
public function activate($id, $token, Request $request)
{
Log::info('Full Request URL: ' . $request->fullUrl());
try {
$user = User::find($id);
@@ -492,7 +496,6 @@ class UsersController extends Controller
], 404);
}
$token = $request->query('token');
if (!$token) {
Log::error("Token missing for User ID: {$id}");
return response()->json([
@@ -502,7 +505,8 @@ class UsersController extends Controller
}
// Update password in Laravel
$user->password = Hash::make('password');
$user->password = Hash::make($request->password);
$user->user_credentials_enabled = 1;
$user->save();
Log::info("Password updated for User ID: {$id} in Laravel.");
@@ -665,12 +669,16 @@ class UsersController extends Controller
$user = User::where('email', $email)->first();
if ($user) {
$token = JWTAuth::fromUser($user);
$localResponse = [
'type' => 1,
'status' => true,
'message' => 'Login successful (Local). Redirecting to Local dashboard...',
'user_id' => $user->id,
'email' => $email,
'dashboard_url' => url('/dashboard')
'data' => [
'access_token' => $token,
'user' => $user,
],
];
} else {
$localResponse = [
@@ -679,13 +687,10 @@ class UsersController extends Controller
];
}
$thingsboardResponse = $this->adminService->getUserByEmailThingsBoard($email);
// $thingsboardResponse = $this->adminService->getUserByEmailThingsBoard($email);
// ✅ Return both responses
return response()->json([
'local' => $localResponse,
'thingsboard' => $thingsboardResponse
], 200);
return response()->json($localResponse);
}
@@ -755,4 +760,91 @@ class UsersController extends Controller
return jsonResponseWithErrorMessage($e->getMessage(), 500);
}
}
public function userEmailCheck(Request $request)
{
try {
$validator = Validator::make($request->all(), [
'email' => 'required'
]);
if ($validator->fails()) {
return response()->json([
'success' => false,
'message' => 'Validation failed',
'errors' => $validator->errors()
], 422);
}
$email = $request->input('email');
$user = User::where('email', $email)->first();
if ($user) {
// If user
$mailData = [
'name' => $user->first_name,
'user_id' => $user->id,
];
Mail::to($user->email)->send(new UserLink($mailData));
return response()->json([
'success' => true,
'message' => 'Email exists',
'user_id' => $user->id
], 200);
}
return response()->json([
'success' => false,
'message' => 'Email does not exist'
], 404);
} catch (Exception $e) {
Log::error("An error occurred while checking email: " . $e->getMessage());
return response()->json(['error' => 'Failed to check email', 'details' => $e->getMessage()], 500);
}
}
public function userUpdatePassword(Request $request)
{
try {
$validator = Validator::make($request->all(), [
'user_id' => 'required',
'password' => 'required'
]);
if ($validator->fails()) {
return response()->json([
'success' => false,
'message' => 'Validation failed',
'errors' => $validator->errors()
], 422);
}
$userId = $request->input('user_id');
$password = $request->input('password');
$user = User::find($userId);
if (!$user) {
return response()->json([
'success' => false,
'message' => 'User not found'
], 404);
}
// Update password
$user->password = Hash::make($password);
$user->save();
return response()->json([
'success' => true,
'message' => 'Password updated successfully'
], 200);
} catch (Exception $e) {
Log::error("An error occurred while updating password: " . $e->getMessage());
return response()->json(['error' => 'Failed to update password', 'details' => $e->getMessage()], 500);
}
}
}

View File

@@ -35,6 +35,7 @@ class AuthController extends Controller
return jsonResponseWithErrorMessageApi($validationErrors, 403);
}
$isExistEmail = User::where('email', $request->email)->first();
if ($isExistEmail == null) {
return jsonResponseWithErrorMessageApi(__('auth.incorrect_email'), 403);
}
@@ -57,7 +58,7 @@ class AuthController extends Controller
'user' => $user,
];
return jsonResponseWithSuccessMessage(__('auth.data_fetched_successfully'), $response, 200);
return jsonResponseWithSuccessMessage(__('auth.data_fetched_successfully'), $response, 2);
}
}
catch (QueryException $e) {

View File

@@ -23,7 +23,7 @@ class CustomerDeviceInfoController extends Controller
$this->customerInfoService = $customerInfoService;
}
@@ -243,7 +243,7 @@ class CustomerDeviceInfoController extends Controller
$telemetryResponse = Http::withHeaders([
'accept' => 'application/json',
'Authorization' => 'Bearer ' . $bearerToken,
])->get("$apiBaseUrl/api/plugins/telemetry/DEVICE/{$device->id}/values/timeseries", [
])->get("{$apiBaseUrl}api/plugins/telemetry/DEVICE/{$device->id}/values/timeseries", [
'useStrictDataTypes' => 'false'
]);
@@ -325,4 +325,31 @@ class CustomerDeviceInfoController extends Controller
return ($alarm['createdTime'] ?? 0) >= $twentyFourHoursAgo;
}));
}
public function userInfo(Request $request){
try{
$token = readHeaderToken();
$userId = $token['sub'];
$user = User::find($userId);
if(!$user){
return response()->json([
'success' => false,
'error' => 'user_not_found',
'message' => 'User not found'
], 404);
}
return response()->json($user);
} catch(\Exception $e){
return response()->json([
'success' => false,
'error' => 'server_error',
'message' => 'An error occurred while fetching user information',
'details' => $e->getMessage()
], 500);
}
}
}

File diff suppressed because it is too large Load Diff

View File

@@ -320,7 +320,7 @@ class UserAssetLinkController extends Controller
$deviceResponse = Http::withHeaders([
'accept' => 'application/json',
'Authorization' => 'Bearer ' . $bearerToken,
])->get("$apiBaseUrl/api/customer/{$device->customer_id}/deviceInfos", [
])->get("{$apiBaseUrl}api/customer/{$device->customer_id}/deviceInfos", [
'pageSize' => 100,
'page' => 0
]);
@@ -349,7 +349,7 @@ class UserAssetLinkController extends Controller
$dailyResponse = Http::withHeaders([
'accept' => 'application/json',
'Authorization' => 'Bearer ' . $bearerToken,
])->get("$apiBaseUrl/api/plugins/telemetry/DEVICE/{$device->id}/values/timeseries", [
])->get("{$apiBaseUrl}api/plugins/telemetry/DEVICE/{$device->id}/values/timeseries", [
'startTs' => $startOfDay->timestamp * 1000,
'endTs' => $endOfDay->timestamp * 1000,
'useStrictDataTypes' => 'false'
@@ -380,7 +380,7 @@ class UserAssetLinkController extends Controller
$telemetryResponse = Http::withHeaders([
'accept' => 'application/json',
'Authorization' => 'Bearer ' . $bearerToken,
])->get("$apiBaseUrl/api/plugins/telemetry/DEVICE/{$device->id}/values/timeseries");
])->get("{$apiBaseUrl}api/plugins/telemetry/DEVICE/{$device->id}/values/timeseries");
$telemetryData = $telemetryResponse->successful() ? $telemetryResponse->json() : [];

View File

@@ -27,6 +27,7 @@ class AlarmControllerCommon extends Controller
public function createOrUpdateAlarm(Request $request)
{
try {
$alarmData = [
'type' => $request->type ?? null,
'severity' => $request->severity ?? null,
@@ -40,8 +41,6 @@ class AlarmControllerCommon extends Controller
'propagateToTenant' => true,
'originator' => $request->originator ?? 1,
// 'assigneeId' => $request->assigneeId ?? 1,
];
// Handle updating existing alarm
@@ -73,7 +72,7 @@ class AlarmControllerCommon extends Controller
{
try {
$token = app('App\Services\AdminService')->getToken(); // Fetch cached token
$url = env('THINGSBOARD_URL') . "/api/alarm/{$id}";
$url = env('THINGSBOARD_URL') . "api/alarm/{$id}";
$response = Http::withHeaders([
'X-Authorization' => 'Bearer ' . $token,
@@ -109,7 +108,7 @@ class AlarmControllerCommon extends Controller
{
try {
$token = app('App\Services\AdminService')->getToken(); // Fetch cached token0
$url = env('THINGSBOARD_URL') . "/api/alarm/{$id}";
$url = env('THINGSBOARD_URL') . "api/alarm/{$id}";
$getResponse = Http::withHeaders([
'X-Authorization' => 'Bearer ' . $token,
@@ -131,7 +130,7 @@ class AlarmControllerCommon extends Controller
]);
}
$ackUrl = env('THINGSBOARD_URL') . "/api/alarm/{$id}/ack";
$ackUrl = env('THINGSBOARD_URL') . "api/alarm/{$id}/ack";
$ackResponse = Http::withHeaders([
'X-Authorization' => 'Bearer ' . $token,
@@ -161,7 +160,7 @@ class AlarmControllerCommon extends Controller
{
try {
$token = app(AdminService::class)->getToken(); // Fetch cached token
$url = env('THINGSBOARD_URL') . "/api/alarm/{$id}";
$url = env('THINGSBOARD_URL') . "api/alarm/{$id}";
// Fetch the alarm details first
$getResponse = Http::withHeaders([
@@ -185,7 +184,7 @@ class AlarmControllerCommon extends Controller
}
// Clear the alarm
$clearUrl = env('THINGSBOARD_URL') . "/api/alarm/{$id}/clear";
$clearUrl = env('THINGSBOARD_URL') . "api/alarm/{$id}/clear";
$clearResponse = Http::withHeaders([
'X-Authorization' => 'Bearer ' . $token,
'accept' => 'application/json',
@@ -215,7 +214,7 @@ class AlarmControllerCommon extends Controller
public function filterAlarm(Request $request)
{
try {
// dd('alarm');
$alarmData = $request->only([
'severity',
'pageSize',
@@ -243,8 +242,6 @@ class AlarmControllerCommon extends Controller
}
public function getDeviceAlarms(Request $request)
{
$validator = Validator::make($request->all(), [
@@ -280,7 +277,7 @@ class AlarmControllerCommon extends Controller
$response = Http::withHeaders([
'Authorization' => "Bearer $token",
'Accept' => 'application/json',
])->get("$baseUrl/api/v2/alarms", [
])->get("{$baseUrl}api/v2/alarms", [
'statusList' => 'ACTIVE',
'severityList' => 'CRITICAL,MAJOR,MINOR,WARNING',
'pageSize' => $pageSize,

View File

@@ -93,11 +93,12 @@ if (!function_exists('jsonResponseWithErrorMessage')) {
if (!function_exists('jsonResponseWithSuccessMessage')) {
function jsonResponseWithSuccessMessage($message, $data = [])
function jsonResponseWithSuccessMessage($message, $data = [],$type = null)
{
$statusCode = 200;
// Prepare the response array
$response = [
'type' => $type,
'status' => 'success',
'status_code' => $statusCode,
'message' => $message,
@@ -376,37 +377,60 @@ function parameters()
{
$keys = [
// 1. Gas Engine
"4e989080-04ad-11f0-a9dc-45dd276e4cd5" => [
"keyNameList1" => 'PowerLoss_value,ChannelSpeed',
"keyNameList2" => 'MechanicalHealth_valueInHealth,ChannelSpeed',
],
// 2. 2 Stroke Engine
"88986090-16b3-11f0-a9dc-45dd276e4cd5" => [
"keyNameList1" => 'PowerLoss_value,ChannelSpeed',
"keyNameList2" => 'MechanicalHealth_valueInHealth,ChannelSpeed',
],
// 3. Engine
"a7802800-f34d-11ef-a9dc-45dd276e4cd5" => [
"keyNameList1" => 'PowerLoss_value,ChannelSpeed',
"keyNameList2" => 'MechanicalHealth_valueInHealth,ChannelSpeed',
],
// 4. Bearing
"b82d42a0-f34d-11ef-a9dc-45dd276e4cd5" => [
"keyNameList1" => 'GlobalMixed_valueInPercent,ChannelSpeed',
"keyNameList2" => 'BearingGlobal_valueInPercent,ChannelSpeed',
"keyNameList2" => 'BearingGlobal_valueInPercent,GlobalKurto_valueInPercent,ChannelSpeed',
],
// 5. Gearbox
"b60d08f0-16b3-11f0-a9dc-45dd276e4cd5" => [
"keyNameList1" => 'GlobalMixed_valueInPercent,ChannelSpeed',
"keyNameList2" => 'BearingGlobal_valueInPercent,ChannelSpeed',
],
// 6. Turbine
"b13497a0-f34d-11ef-a9dc-45dd276e4cd5" => [
"keyNameList1" => 'RegularityDeviation_valueInPercent,BladeStatus_valueInPercent,ChannelSpeed',
"keyNameList2" => 'BearingStatus_valueInPercent,TurbineCoupling_valueInPercent,ChannelSpeed',
],
// 7. Gas Turbine
"72907b10-04ad-11f0-a9dc-45dd276e4cd5" => [
"keyNameList1" => 'RegularityDeviation_valueInPercent,BladeStatus_valueInPercent,ChannelSpeed',
"keyNameList2" => 'BearingStatus_valueInPercent,TurbineCoupling_valueInPercent,ChannelSpeed',
],
// 8. Torque
"bfbd2490-f34d-11ef-a9dc-45dd276e4cd5" => [
"keyNameList1" => 'StaticTorque_value,ChannelSpeed',
"keyNameList2" => 'StaticPower_value,ChannelSpeed',
],
// 9. Oil
"bfd52480-15eb-11f0-a9dc-45dd276e4cd5" => [
"keyNameList1" => 'OT',
"keyNameList2" => 'TDN',
],
// 10. Propeller
"6543c980-04ad-11f0-a9dc-45dd276e4cd5" => [
"keyNameList1" => 'PropellerEfficiency_value,ChannelSpeed',
"keyNameList2" => 'PropellerBearing_valueInPercent,PropellerUnbalance_valueInPercent,ChannelSpeed',
],
// 11. Motor
"6c686680-04ad-11f0-a9dc-45dd276e4cd5" => [
"keyNameList1" => 'MElectromag_valueInPercent,ChannelSpeed',
"keyNameList2" => 'MStressStability_valueInPercent,MBearing_valueInPercent,ChannelSpeed',
]
];

View File

@@ -25,12 +25,20 @@ class CreateDeviceRequest extends FormRequest
{
// Log::info("CreateDeviceRequest: " . json_encode($this->all()));
return [
'name' => 'required|string',
// 'type' => 'required|string|max:255',
'name' => 'required|string|max:255',
'label' => 'required|string|max:255',
'customerId' => 'required',
'customerId' => 'required|integer',
'asset_id' => 'required|string',
];
}
public function messages()
{
return [
'name.required' => 'Name is required!',
'label.required' => 'Label is required!',
'customerId.required' => 'Customer is required!',
'asset_id.required' => 'Asset is required!',
];
}
}

56
app/Mail/UserLink.php Normal file
View File

@@ -0,0 +1,56 @@
<?php
namespace App\Mail;
use Illuminate\Bus\Queueable;
use Illuminate\Contracts\Queue\ShouldQueue;
use Illuminate\Mail\Mailable;
use Illuminate\Mail\Mailables\Content;
use Illuminate\Mail\Mailables\Envelope;
use Illuminate\Queue\SerializesModels;
class UserLink extends Mailable
{
use Queueable, SerializesModels;
public $mailData;
/**
* Create a new message instance.
*/
public function __construct($mailData)
{
$this->mailData = $mailData;
}
/**
* Get the message envelope.
*/
public function envelope(): Envelope
{
return new Envelope(
subject: 'Update Password',
);
}
/**
* Get the message content definition.
*/
public function content(): Content
{
return new Content(
view: 'Mails.user_update_password',
with: ['mailData' => $this->mailData],
);
}
/**
* Get the attachments for the message.
*
* @return array<int, \Illuminate\Mail\Mailables\Attachment>
*/
public function attachments(): array
{
return [];
}
}

View File

@@ -23,6 +23,9 @@ class Device extends Model
'device_profile_id',
'tenant_id',
'customer_id',
'speed_limit',
'torque_limit',
'power_limit',
'label',
'version',
'active',

View File

@@ -11,7 +11,10 @@ class AppServiceProvider extends ServiceProvider
*/
public function register(): void
{
//
if ($this->app->environment('local') && class_exists(\Laravel\Telescope\TelescopeServiceProvider::class)) {
$this->app->register(\Laravel\Telescope\TelescopeServiceProvider::class);
$this->app->register(TelescopeServiceProvider::class);
}
}
/**

View File

@@ -0,0 +1,64 @@
<?php
namespace App\Providers;
use Illuminate\Support\Facades\Gate;
use Laravel\Telescope\IncomingEntry;
use Laravel\Telescope\Telescope;
use Laravel\Telescope\TelescopeApplicationServiceProvider;
class TelescopeServiceProvider extends TelescopeApplicationServiceProvider
{
/**
* Register any application services.
*/
public function register(): void
{
// Telescope::night();
$this->hideSensitiveRequestDetails();
$isLocal = $this->app->environment('local');
Telescope::filter(function (IncomingEntry $entry) use ($isLocal) {
return $isLocal ||
$entry->isReportableException() ||
$entry->isFailedRequest() ||
$entry->isFailedJob() ||
$entry->isScheduledTask() ||
$entry->hasMonitoredTag();
});
}
/**
* Prevent sensitive request details from being logged by Telescope.
*/
protected function hideSensitiveRequestDetails(): void
{
if ($this->app->environment('local')) {
return;
}
Telescope::hideRequestParameters(['_token']);
Telescope::hideRequestHeaders([
'cookie',
'x-csrf-token',
'x-xsrf-token',
]);
}
/**
* Register the Telescope gate.
*
* This gate determines who can access Telescope in non-local environments.
*/
protected function gate(): void
{
Gate::define('viewTelescope', function ($user) {
return in_array($user->email, [
//
]);
});
}
}

View File

@@ -34,7 +34,7 @@ class AdminDeviceProfileMaster
// '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,
]);
@@ -51,5 +51,5 @@ class AdminDeviceProfileMaster
}
}

View File

@@ -92,7 +92,7 @@ class AdminService
// throw new Exception('Failed to create asset: ' . $response->body());
// }
// }
// public function createAsset(array $data)
// {
// $token = $this->getToken();
@@ -150,7 +150,7 @@ class AdminService
'Accept' => 'application/json',
'Content-Type' => 'application/json',
])->withBody(json_encode($payload), 'application/json')
->post("{$this->baseUrl}/api/asset");
->post("{$this->baseUrl}api/asset");
if ($response->successful()) {
return $response->json();
@@ -206,7 +206,7 @@ class AdminService
$url = "{$this->baseUrl}/api/customer";
$url = "{$this->baseUrl}api/customer";
$method = 'post';
// Send request
$response = Http::withHeaders([
@@ -267,7 +267,7 @@ class AdminService
'Content-Type' => 'application/json',
])
->timeout(30)
->post("{$this->baseUrl}/api/user", $payload);
->post("{$this->baseUrl}api/user", $payload);
if ($response->successful()) {
return $response->json();
@@ -310,7 +310,7 @@ class AdminService
'Authorization' => "Bearer $token",
'Accept' => 'application/json',
'Content-Type' => 'application/json',
])->delete("{$this->baseUrl}/api/asset/{$assetId}");
])->delete("{$this->baseUrl}api/asset/{$assetId}");
Log::info('Asset Deletion Response: ' . $response);
@@ -360,7 +360,7 @@ class AdminService
'Authorization' => "Bearer $token",
'Accept' => 'application/json',
'Content-Type' => 'application/json',
])->post("{$this->baseUrl}/api/customer/{$customerId}/asset/{$assetId}");
])->post("{$this->baseUrl}api/customer/{$customerId}/asset/{$assetId}");
// Log the response for debugging purposes
Log::info('Asset Assignment Response: ' . $response->body());
@@ -381,7 +381,7 @@ class AdminService
$token = $this->getToken();
$url = "{$this->baseUrl}/api/customer/{$data['customerId']}";
$url = "{$this->baseUrl}api/customer/{$data['customerId']}";
$response = Http::withHeaders([
'Authorization' => "Bearer $token",
@@ -413,9 +413,10 @@ class AdminService
$token = $this->getToken();
$response = Http::withHeaders([
'Authorization' => "Bearer $token",
'X-Authorization' => "Bearer $token",
'accept' => 'application/json',
])->get("{$this->baseUrl}/api/users?pageSize=100&page=0");
'Content-Type' => 'application/json',
])->get("{$this->baseUrl}api/users?pageSize=100&page=0");
if ($response->successful()) {
return $response->json();
@@ -432,7 +433,7 @@ class AdminService
$response = Http::withHeaders([
'Authorization' => "Bearer $token",
'accept' => 'application/json',
])->delete("{$this->baseUrl}/api/user/{$userId}");
])->delete("{$this->baseUrl}api/user/{$userId}");
if ($response->failed()) {
Log::error('ThingsBoard deletion failed - Status: ' . $response->status() . ' - Body: ' . $response->body());
@@ -499,7 +500,7 @@ class AdminService
$searchResponse = Http::withHeaders([
'Authorization' => "Bearer $token",
'accept' => 'application/json'
])->get("{$this->baseUrl}/api/users?pageSize=1&page=0&textSearch={$user->email}");
])->get("{$this->baseUrl}api/users?pageSize=1&page=0&textSearch={$user->email}");
if ($searchResponse->successful() && !empty($searchResponse['data'])) {
$tbUser = $searchResponse['data'][0];
@@ -509,7 +510,7 @@ class AdminService
Http::withHeaders([
'Authorization' => "Bearer $token",
'Content-Type' => 'application/json'
])->post("{$this->baseUrl}/api/user", [
])->post("{$this->baseUrl}api/user", [
'id' => ['id' => $tbUserId],
// 'email' => $dummyEmail,
'authority' => $tbUser['authority'],
@@ -530,7 +531,7 @@ class AdminService
// 'email' => $dummyEmail
];
$activationUrl = "{$this->baseUrl}/api/noauth/activate";
$activationUrl = "{$this->baseUrl}api/noauth/activate";
$response = Http::withHeaders([
'Content-Type' => 'application/json',
@@ -608,7 +609,7 @@ class AdminService
$response = Http::withHeaders([
'Authorization' => "Bearer $token",
'accept' => 'application/json',
])->get("{$this->baseUrl}/api/users?pageSize=100&page=0");
])->get("{$this->baseUrl}api/users?pageSize=100&page=0");
if ($response->successful()) {
return $response->json();

View File

@@ -41,7 +41,7 @@ class AlarmService
'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,
]);
@@ -255,67 +255,78 @@ class AlarmService
public function getTelemetryData($device, $keyNames, $startTs, $endTs)
/**
* Get telemetry data for a specific device and keys
*
* @param Device $device The device to get telemetry for
* @param array $keyNames Array of telemetry keys to fetch
* @param int $startTs Start timestamp
* @param int $endTs End timestamp
* @return array Telemetry data or error response
*/
public function getTelemetryData(Device $device, array $keyNames, int $startTs, int $endTs): array
{
$token = $this->adminService->getToken();
try {
$token = $this->adminService->getToken();
if (!$token) {
Log::error('Failed to fetch ThingsBoard token');
return ['error' => 'Failed to fetch ThingsBoard token'];
}
if (!$token) {
Log::error('Failed to fetch ThingsBoard token');
return ['error' => 'Failed to fetch ThingsBoard token'];
}
$baseUrl = env('THINGSBOARD_URL');
$deviceId = $device->id;
$baseUrl = env('THINGSBOARD_URL');
$deviceId = $device->id;
$keys = implode(',', $keyNames);
$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()
$response = Http::withHeaders([
'Authorization' => "Bearer $token",
'Accept' => 'application/json'
])->get("{$baseUrl}api/plugins/telemetry/DEVICE/{$deviceId}/values/timeseries", [
'keys' => $keys,
'startTs' => $startTs,
'interval' => $endTs,
'limit' => 100,
'useStrictDataTypes' => false
]);
return ['error' => "Failed to fetch telemetry. HTTP Code: " . $response->status()];
}
if (!$response->successful()) {
Log::error("Failed to fetch telemetry for device: {$device->name}", [
'device_id' => $deviceId,
'http_code' => $response->status(),
'url' => $response->effectiveUri(),
'response' => $response->body()
]);
// Decode the telemetry response
$telemetry = $response->json();
return ['error' => "Failed to fetch telemetry. HTTP Code: " . $response->status()];
}
if (json_last_error() !== JSON_ERROR_NONE) {
Log::error("Failed to decode telemetry response for device: {$device->name}", [
'response' => $response->body()
$telemetry = $response->json();
if (json_last_error() !== JSON_ERROR_NONE) {
Log::error("Failed to decode telemetry response for device: {$device->name}", [
'device_id' => $deviceId,
'response' => $response->body()
]);
return ['error' => 'Invalid telemetry response format'];
}
return $telemetry;
} catch (\Exception $e) {
Log::error("Unexpected error in getTelemetryData", [
'device_id' => $device->id,
'error' => $e->getMessage(),
'trace' => $e->getTraceAsString()
]);
return ['error' => 'Invalid telemetry response format'];
return ['error' => 'An unexpected error occurred while fetching telemetry data'];
}
return $telemetry;
}
public function filterAlarm(array $data)
{
$token = $this->getToken();
$deviceId = null;
if (!empty($data['deviceId'])) {
@@ -345,7 +356,7 @@ class AlarmService
return $value !== null;
});
$url = "{$this->baseUrl}/api/v2/alarms" . (count($queryParams) ? '?' . http_build_query($queryParams) : '');
$url = "{$this->baseUrl}api/v2/alarms" . (count($queryParams) ? '?' . http_build_query($queryParams) : '');
$response = Http::withHeaders([
'Authorization' => "Bearer $token",
@@ -415,7 +426,7 @@ class AlarmService
$url = "{$this->baseUrl}/api/alarm";
$url = "{$this->baseUrl}api/alarm";
$method = 'post';
$response = Http::withHeaders([

View File

@@ -92,7 +92,7 @@ class CustomerInfoService
$response = Http::withHeaders([
'Authorization' => "Bearer $token",
'Accept' => 'application/json',
])->get("$baseUrl/api/plugins/telemetry/DEVICE/{$deviceId}/values/timeseries", $queryParams);
])->get("{$baseUrl}api/plugins/telemetry/DEVICE/{$deviceId}/values/timeseries", $queryParams);
// Check if the response was successful
if (!$response->successful()) {
@@ -153,7 +153,7 @@ class CustomerInfoService
$response = Http::withHeaders([
'Authorization' => "Bearer $token",
'Accept' => 'application/json',
])->get("$baseUrl/api/plugins/telemetry/DEVICE/{$deviceId}/values/timeseries", $queryParams);
])->get("{$baseUrl}api/plugins/telemetry/DEVICE/{$deviceId}/values/timeseries", $queryParams);
@@ -372,7 +372,7 @@ class CustomerInfoService
// 'accept' => 'application/json',
'Content-Type' => 'application/json',
])
->post("{$baseUrl}/api/auth/login", [
->post("{$baseUrl}api/auth/login", [
'username' => $username,
'password' => $password,
]);
@@ -451,7 +451,7 @@ class CustomerInfoService
'keys' => $keys,
'startTs' => $ts['startTs'] ?? null,
'endTs' => $ts['endTs'] ?? null,
'limit' => $ts ? 25000 : null
'limit' => 250
]);
if ($response->successful()) {
@@ -470,35 +470,17 @@ class CustomerInfoService
], 500);
}
}
public function getDevicesCount($deviceIds){
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';
$url = env('THINGSBOARD_URL') . 'api/entitiesQuery/find';
// ---------- 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 = [
$payload = [
"entityFilter" => [
"type" => "entityList",
"entityType" => "DEVICE",
@@ -520,30 +502,115 @@ class CustomerInfoService
"type" => "BOOLEAN"
]
]
],
"pageLink" => [
"pageSize" => 100,
"page" => 0,
"sortOrder" => [
"key" => [
"type" => "ENTITY_FIELD",
"key" => "name"
],
"direction" => "ASC"
]
]
];
$activeResponse = Http::withHeaders([
$response = Http::withHeaders([
'accept' => 'application/json',
'Content-Type' => 'application/json',
'X-Authorization' => 'Bearer ' . $token,
])->post($url, $activePayload);
])->post($url, $payload);
$activeCount = $activeResponse->json() ?? 0;
if ($response->successful()) {
$data = $response->json();
return [
'totalDevices' => count($deviceIds),
'activeDevices' => count($data['data'] ?? [])
];
}
// ---------- Return both counts ----------
return [
'totalDevices' => $totalCount,
'activeDevices' => $activeCount
'totalDevices' => count($deviceIds),
'activeDevices' => 0
];
} catch(Exception $e){
return response()->json(['success' => false, 'message' => $e->getMessage()], 500);
} catch (\Exception $e) {
Log::error('Failed to get devices count: ' . $e->getMessage());
return [
'totalDevices' => count($deviceIds),
'activeDevices' => 0
];
}
}
public function fetchDeviceAlarms(array $deviceIds)
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();
@@ -552,16 +619,25 @@ public function fetchDeviceAlarms(array $deviceIds)
}
$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 = now()->subDays(30)->timestamp * 1000;
$endTs = now()->timestamp * 1000;
$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" => $deviceIds
"entityList" => $entityList
],
"pageLink" => [
"startTs" => $startTs,
@@ -569,6 +645,8 @@ public function fetchDeviceAlarms(array $deviceIds)
"pageSize" => 100,
"page" => 0,
"textSearch" => "",
"statusList" => $data['statusList'] ?? ['ACTIVE'],
"severityList" => $data['severityList'] ?? [],
"sortOrder" => [
"key" => [
"type" => "ALARM_FIELD",

View File

@@ -31,7 +31,7 @@ class DeviceService
'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,
]);
@@ -96,7 +96,7 @@ class DeviceService
$url = "{$this->baseUrl}/api/device";
$url = "{$this->baseUrl}api/device";
$method = 'post';
$response = Http::withHeaders([
@@ -122,7 +122,7 @@ class DeviceService
$token = $this->getToken();
$url = "{$this->baseUrl}/api/device/{$data['deviceId']}";
$url = "{$this->baseUrl}api/device/{$data['deviceId']}";
$response = Http::withHeaders([
'Authorization' => "Bearer $token",

View File

@@ -37,7 +37,7 @@ class RuleChainService
'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,
]);
@@ -63,7 +63,7 @@ class RuleChainService
'accept' => 'application/json',
'Content-Type' => 'application/json',
'X-Authorization' => "Bearer {$token}",
])->get("{$this->baseUrl}/api/ruleChains", [
])->get("{$this->baseUrl}api/ruleChains", [
'page' => $page,
'pageSize' => $pageSize,
'sortProperty' => 'createdTime',
@@ -93,7 +93,7 @@ class RuleChainService
'accept' => 'application/json',
'Content-Type' => 'application/json',
'X-Authorization' => "Bearer {$token}",
])->get("{$this->baseUrl}/api/ruleChains/export", [
])->get("{$this->baseUrl}api/ruleChains/export", [
'limit' => $limit
]);
@@ -119,7 +119,7 @@ class RuleChainService
'accept' => 'application/json',
'Content-Type' => 'application/json',
'X-Authorization' => "Bearer {$token}",
])->get("{$this->baseUrl}/api/ruleChain/{$ruleChainId}");
])->get("{$this->baseUrl}api/ruleChain/{$ruleChainId}");
if ($response->successful()) {
return $response->json();

View File

@@ -0,0 +1,212 @@
<?php
namespace App\Services;
use App\Models\Device;
use App\Models\TimeseriesKeyMaster;
use App\Models\TimeseriesAlertMessage;
use Illuminate\Support\Facades\Cache;
use Illuminate\Support\Facades\Log;
use Carbon\Carbon;
class TelemetryService
{
protected $customerInfoService;
protected $adminService;
public function __construct(CustomerInfoService $customerInfoService, AdminService $adminService)
{
$this->customerInfoService = $customerInfoService;
$this->adminService = $adminService;
}
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;
} elseif ($value['value'] > 2.5 && $value['value'] < 5) {
$hasOrange = true;
}
} else {
if ($value['value'] > 0 && $value['value'] < 31) {
$hasRed = true;
break;
} elseif ($value['value'] < 71) {
$hasOrange = true;
}
}
}
return $hasRed ? 'red' : ($hasOrange ? 'orange' : 'green');
}
public function getAssetHealth(array $deviceHealthStatuses): string
{
if (in_array('red', $deviceHealthStatuses)) {
return 'red';
}
return in_array('orange', $deviceHealthStatuses) ? 'orange' : 'green';
}
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 getThresholdMap(): array
{
return [
'ChannelSpeed' => [
['threshold' => 5000, 'color' => 'green']
],
'StaticTorque_value' => [
['threshold' => 5000, 'color' => 'green']
],
'StaticPower_value' => [
['threshold' => 5000, 'color' => 'green']
],
'PropellerEfficiency_value' => [
['threshold' => 3, 'color' => 'green'],
['threshold' => 4.5, 'color' => 'orange'],
['threshold' => 6, 'color' => 'orange']
],
'StaticTorsion_value' => [
['threshold' => 2.5, 'color' => 'green'],
['threshold' => 5, 'color' => 'orange'],
['threshold' => 7.5, 'color' => 'orange']
],
'PowerLoss_value' => [
['threshold' => 3, 'color' => 'green'],
['threshold' => 6, 'color' => 'orange'],
['threshold' => 10, 'color' => 'red']
],
'GlobalLevel_value' => [
['threshold' => 2, 'color' => 'green'],
['threshold' => 6, 'color' => 'orange'],
['threshold' => 8, 'color' => 'orange']
],
'TDN' => [
['threshold' => 400, 'color' => 'red'],
['threshold' => 550, 'color' => 'orange'],
['threshold' => 700, 'color' => 'orange']
],
'OT' => [
['threshold' => 30, 'color' => 'blue'],
['threshold' => 50, 'color' => 'blue'],
['threshold' => 70, 'color' => 'red'],
],
'AT' => [
['threshold' => 30, 'color' => 'blue'],
['threshold' => 50, 'color' => 'blue'],
['threshold' => 70, 'color' => 'red'],
],
'default' => [
['threshold' => 30, 'color' => 'red'],
['threshold' => 50, 'color' => 'orange'],
['threshold' => 70, 'color' => 'orange']
]
];
}
public function getThresholdLimit($deviceId): array
{
$device = Device::find($deviceId);
return [
'ChannelSpeed' => [
['min' => 0, 'max' => $device->speed_limit ?? 50000]
],
'PowerLoss_value' => [
['min' => 0, 'max' => 10]
],
'GlobalLevel_value' => [
['min' => 0, 'max' => 10]
],
'StaticTorque_value' => [
['min' => 0, 'max' => $device->torque_limit ?? 50000]
],
'StaticPower_value' => [
['min' => 0, 'max' => $device->power_limit ?? 500000]
],
'PropellerEfficiency_value' => [
['min' => 0, 'max' => 10]
],
'StaticTorsion_value' => [
['min' => 0, 'max' => 6]
],
'TDN' => [
['min' => 0, 'max' => 1400]
],
'OT' => [
['min' => 0, 'max' => 100]
],
'AT' => [
['min' => 0, 'max' => 100]
],
'default' => [
['min' => 0, 'max' => 100]
]
];
}
public function getHealthStatus(float $value, array $thresholds): string
{
foreach ($thresholds as $t) {
if ($value < $t['threshold']) {
return match ($t['color']) {
'red' => 'Alert',
'orange' => 'Attention',
'green' => 'Stable',
default => $t['threshold'] == 70 ? 'Stable' : 'Alert'
};
}
}
return 'Stable';
}
public function transformTelemetryData(string $deviceId, array $data, array $displayNameMap, bool $isActive): array
{
$transformedTelemetry = [];
$dateTime = null;
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');
$value = $item['value'];
$thresholds = $this->getThresholdMap()[$key] ?? $this->getThresholdMap()['default'];
$thresholdLimits = $this->getThresholdLimit($deviceId)[$key] ?? $this->getThresholdLimit($deviceId)['default'];
$status = $this->getHealthStatus($value, $thresholds);
$statusColor = match($status) {
'Alert' => 'red',
'Attention' => 'orange',
'Stable' => 'green'
};
$transformedTelemetry[] = [
'display_name' => $displayNameMap[$key] ?? $key,
'value' => number_format((float)$value, 2, '.', ''),
'health_status' => !$isActive ? 'Offline' : $status,
'status_color' => !$isActive ? 'gray' : $statusColor,
'thresholds' => $thresholds,
'limit' => $thresholdLimits
];
}
}
}
return [
'telemetry' => $transformedTelemetry,
'dateTime' => $dateTime
];
}
}

View File

@@ -3,4 +3,5 @@
return [
App\Providers\AppServiceProvider::class,
App\Providers\RouteServiceProvider::class,
// App\Providers\TelescopeServiceProvider::class,
];

View File

@@ -18,6 +18,7 @@
"laravel/pail": "^1.2.2",
"laravel/pint": "^1.13",
"laravel/sail": "^1.41",
"laravel/telescope": "^5.7",
"mockery/mockery": "^1.6",
"nunomaduro/collision": "^8.6",
"phpunit/phpunit": "^11.5.3"
@@ -61,7 +62,9 @@
},
"extra": {
"laravel": {
"dont-discover": []
"dont-discover": [
"laravel/telescope"
]
}
},
"config": {

73
composer.lock generated
View File

@@ -4,7 +4,7 @@
"Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies",
"This file is @generated automatically"
],
"content-hash": "1bba97d230b8ab68157468ff078d2d97",
"content-hash": "8d3d61a18d5d707559ad51cadb5c7248",
"packages": [
{
"name": "brick/math",
@@ -7058,6 +7058,75 @@
},
"time": "2025-01-24T15:45:36+00:00"
},
{
"name": "laravel/telescope",
"version": "v5.7.0",
"source": {
"type": "git",
"url": "https://github.com/laravel/telescope.git",
"reference": "440908cb856cfbef9323244f7978ad4bf8cd2daa"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/laravel/telescope/zipball/440908cb856cfbef9323244f7978ad4bf8cd2daa",
"reference": "440908cb856cfbef9323244f7978ad4bf8cd2daa",
"shasum": ""
},
"require": {
"ext-json": "*",
"laravel/framework": "^8.37|^9.0|^10.0|^11.0|^12.0",
"php": "^8.0",
"symfony/console": "^5.3|^6.0|^7.0",
"symfony/var-dumper": "^5.0|^6.0|^7.0"
},
"require-dev": {
"ext-gd": "*",
"guzzlehttp/guzzle": "^6.0|^7.0",
"laravel/octane": "^1.4|^2.0|dev-develop",
"orchestra/testbench": "^6.40|^7.37|^8.17|^9.0|^10.0",
"phpstan/phpstan": "^1.10",
"phpunit/phpunit": "^9.0|^10.5|^11.5"
},
"type": "library",
"extra": {
"laravel": {
"providers": [
"Laravel\\Telescope\\TelescopeServiceProvider"
]
}
},
"autoload": {
"psr-4": {
"Laravel\\Telescope\\": "src/",
"Laravel\\Telescope\\Database\\Factories\\": "database/factories/"
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "Taylor Otwell",
"email": "taylor@laravel.com"
},
{
"name": "Mohamed Said",
"email": "mohamed@laravel.com"
}
],
"description": "An elegant debug assistant for the Laravel framework.",
"keywords": [
"debugging",
"laravel",
"monitoring"
],
"support": {
"issues": "https://github.com/laravel/telescope/issues",
"source": "https://github.com/laravel/telescope/tree/v5.7.0"
},
"time": "2025-03-27T17:25:52+00:00"
},
{
"name": "mockery/mockery",
"version": "1.6.12",
@@ -8951,5 +9020,5 @@
"php": "^8.2"
},
"platform-dev": [],
"plugin-api-version": "2.6.0"
"plugin-api-version": "2.2.0"
}

206
config/telescope.php Normal file
View File

@@ -0,0 +1,206 @@
<?php
use Laravel\Telescope\Http\Middleware\Authorize;
use Laravel\Telescope\Watchers;
return [
/*
|--------------------------------------------------------------------------
| Telescope Master Switch
|--------------------------------------------------------------------------
|
| This option may be used to disable all Telescope watchers regardless
| of their individual configuration, which simply provides a single
| and convenient way to enable or disable Telescope data storage.
|
*/
'enabled' => env('TELESCOPE_ENABLED', true),
/*
|--------------------------------------------------------------------------
| Telescope Domain
|--------------------------------------------------------------------------
|
| This is the subdomain where Telescope will be accessible from. If the
| setting is null, Telescope will reside under the same domain as the
| application. Otherwise, this value will be used as the subdomain.
|
*/
'domain' => env('TELESCOPE_DOMAIN'),
/*
|--------------------------------------------------------------------------
| Telescope Path
|--------------------------------------------------------------------------
|
| This is the URI path where Telescope will be accessible from. Feel free
| to change this path to anything you like. Note that the URI will not
| affect the paths of its internal API that aren't exposed to users.
|
*/
'path' => env('TELESCOPE_PATH', 'telescope'),
/*
|--------------------------------------------------------------------------
| Telescope Storage Driver
|--------------------------------------------------------------------------
|
| This configuration options determines the storage driver that will
| be used to store Telescope's data. In addition, you may set any
| custom options as needed by the particular driver you choose.
|
*/
'driver' => env('TELESCOPE_DRIVER', 'database'),
'storage' => [
'database' => [
'connection' => env('DB_CONNECTION', 'mysql'),
'chunk' => 1000,
],
],
/*
|--------------------------------------------------------------------------
| Telescope Queue
|--------------------------------------------------------------------------
|
| This configuration options determines the queue connection and queue
| which will be used to process ProcessPendingUpdate jobs. This can
| be changed if you would prefer to use a non-default connection.
|
*/
'queue' => [
'connection' => env('TELESCOPE_QUEUE_CONNECTION', null),
'queue' => env('TELESCOPE_QUEUE', null),
'delay' => env('TELESCOPE_QUEUE_DELAY', 10),
],
/*
|--------------------------------------------------------------------------
| Telescope Route Middleware
|--------------------------------------------------------------------------
|
| These middleware will be assigned to every Telescope route, giving you
| the chance to add your own middleware to this list or change any of
| the existing middleware. Or, you can simply stick with this list.
|
*/
'middleware' => [
'web',
Authorize::class,
],
/*
|--------------------------------------------------------------------------
| Allowed / Ignored Paths & Commands
|--------------------------------------------------------------------------
|
| The following array lists the URI paths and Artisan commands that will
| not be watched by Telescope. In addition to this list, some Laravel
| commands, like migrations and queue commands, are always ignored.
|
*/
'only_paths' => [
// 'api/*'
],
'ignore_paths' => [
'livewire*',
'nova-api*',
'pulse*',
],
'ignore_commands' => [
//
],
/*
|--------------------------------------------------------------------------
| Telescope Watchers
|--------------------------------------------------------------------------
|
| The following array lists the "watchers" that will be registered with
| Telescope. The watchers gather the application's profile data when
| a request or task is executed. Feel free to customize this list.
|
*/
'watchers' => [
Watchers\BatchWatcher::class => env('TELESCOPE_BATCH_WATCHER', true),
Watchers\CacheWatcher::class => [
'enabled' => env('TELESCOPE_CACHE_WATCHER', true),
'hidden' => [],
],
Watchers\ClientRequestWatcher::class => env('TELESCOPE_CLIENT_REQUEST_WATCHER', true),
Watchers\CommandWatcher::class => [
'enabled' => env('TELESCOPE_COMMAND_WATCHER', true),
'ignore' => [],
],
Watchers\DumpWatcher::class => [
'enabled' => env('TELESCOPE_DUMP_WATCHER', true),
'always' => env('TELESCOPE_DUMP_WATCHER_ALWAYS', false),
],
Watchers\EventWatcher::class => [
'enabled' => env('TELESCOPE_EVENT_WATCHER', true),
'ignore' => [],
],
Watchers\ExceptionWatcher::class => env('TELESCOPE_EXCEPTION_WATCHER', true),
Watchers\GateWatcher::class => [
'enabled' => env('TELESCOPE_GATE_WATCHER', true),
'ignore_abilities' => [],
'ignore_packages' => true,
'ignore_paths' => [],
],
Watchers\JobWatcher::class => env('TELESCOPE_JOB_WATCHER', true),
Watchers\LogWatcher::class => [
'enabled' => env('TELESCOPE_LOG_WATCHER', true),
'level' => 'error',
],
Watchers\MailWatcher::class => env('TELESCOPE_MAIL_WATCHER', true),
Watchers\ModelWatcher::class => [
'enabled' => env('TELESCOPE_MODEL_WATCHER', true),
'events' => ['eloquent.*'],
'hydrations' => true,
],
Watchers\NotificationWatcher::class => env('TELESCOPE_NOTIFICATION_WATCHER', true),
Watchers\QueryWatcher::class => [
'enabled' => env('TELESCOPE_QUERY_WATCHER', true),
'ignore_packages' => true,
'ignore_paths' => [],
'slow' => 100,
],
Watchers\RedisWatcher::class => env('TELESCOPE_REDIS_WATCHER', true),
Watchers\RequestWatcher::class => [
'enabled' => env('TELESCOPE_REQUEST_WATCHER', true),
'size_limit' => env('TELESCOPE_RESPONSE_SIZE_LIMIT', 64),
'ignore_http_methods' => [],
'ignore_status_codes' => [],
],
Watchers\ScheduleWatcher::class => env('TELESCOPE_SCHEDULE_WATCHER', true),
Watchers\ViewWatcher::class => env('TELESCOPE_VIEW_WATCHER', true),
],
];

View File

@@ -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('devices', function (Blueprint $table) {
$table->string('sensor')->after('type')->nullable();
});
}
/**
* Reverse the migrations.
*/
public function down(): void
{
Schema::table('devices', function (Blueprint $table) {
$table->dropColumn('sensor');
});
}
};

View File

@@ -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->integer('display_on_popup_sequence')->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_popup_sequence');
});
}
};

View File

@@ -0,0 +1,29 @@
<?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_firing_order')->default(0)->after('display_on_alerts');
$table->tinyInteger('display_cylinder_specific')->default(0)->after('display_firing_order');
});
}
/**
* Reverse the migrations.
*/
public function down(): void
{
Schema::table('timeseries_key_master', function (Blueprint $table) {
$table->dropColumn(['display_firing_order','display_cylinder_specific']);
});
}
};

View File

@@ -0,0 +1,70 @@
<?php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
return new class extends Migration
{
/**
* Get the migration connection name.
*/
public function getConnection(): ?string
{
return config('telescope.storage.database.connection');
}
/**
* Run the migrations.
*/
public function up(): void
{
$schema = Schema::connection($this->getConnection());
$schema->create('telescope_entries', function (Blueprint $table) {
$table->bigIncrements('sequence');
$table->uuid('uuid');
$table->uuid('batch_id');
$table->string('family_hash')->nullable();
$table->boolean('should_display_on_index')->default(true);
$table->string('type', 20);
$table->longText('content');
$table->dateTime('created_at')->nullable();
$table->unique('uuid');
$table->index('batch_id');
$table->index('family_hash');
$table->index('created_at');
$table->index(['type', 'should_display_on_index']);
});
$schema->create('telescope_entries_tags', function (Blueprint $table) {
$table->uuid('entry_uuid');
$table->string('tag');
$table->primary(['entry_uuid', 'tag']);
$table->index('tag');
$table->foreign('entry_uuid')
->references('uuid')
->on('telescope_entries')
->onDelete('cascade');
});
$schema->create('telescope_monitoring', function (Blueprint $table) {
$table->string('tag')->primary();
});
}
/**
* Reverse the migrations.
*/
public function down(): void
{
$schema = Schema::connection($this->getConnection());
$schema->dropIfExists('telescope_entries_tags');
$schema->dropIfExists('telescope_entries');
$schema->dropIfExists('telescope_monitoring');
}
};

View File

@@ -0,0 +1,30 @@
<?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('devices', function (Blueprint $table) {
$table->integer('speed_limit')->nullable()->after('device_profile_id');
$table->integer('torque_limit')->nullable()->after('speed_limit');
$table->integer('power_limit')->nullable()->after('torque_limit');
});
}
/**
* Reverse the migrations.
*/
public function down(): void
{
Schema::table('devices', function (Blueprint $table) {
$table->dropColumn(['speed_limit', 'torque_limit', 'power_limit']);
});
}
};

8
public/vendor/telescope/app-dark.css vendored Normal file

File diff suppressed because one or more lines are too long

7
public/vendor/telescope/app.css vendored Normal file

File diff suppressed because one or more lines are too long

2
public/vendor/telescope/app.js vendored Normal file

File diff suppressed because one or more lines are too long

BIN
public/vendor/telescope/favicon.ico vendored Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 26 KiB

View File

@@ -0,0 +1,5 @@
{
"/app.js": "/app.js?id=99e99836705c54c9dc04352a9907bc7f",
"/app-dark.css": "/app-dark.css?id=1ea407db56c5163ae29311f1f38eb7b9",
"/app.css": "/app.css?id=de4c978567bfd90b38d186937dee5ccf"
}

View File

@@ -0,0 +1,26 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Update Your Password</title>
</head>
<body>
<h1>Hello, {{ $mailData['name'] }}!</h1>
<p>We received a request to update the password for your account.</p>
<p>If you made this request, you can update your password using the link below:</p>
<p>
<a href=" http://vib360.betadelivery.com/forget-password/{{$mailData['user_id'] }}"
style="display: inline-block; padding: 10px 20px; color: #fff; background-color: #007bff; text-decoration: none; border-radius: 5px;">
Update Password
</a>
</p>
<p>If you did not request a password update, no action is needed. Your account is secure.</p>
<p>Thank you,<br>The Support Team</p>
</body>
</html>

View File

@@ -8,6 +8,7 @@ use App\Http\Controllers\APIS\AdminApi\AdminDashboardController;
use App\Http\Controllers\APIS\AdminApi\CustomerController;
use App\Http\Controllers\APIS\AdminApi\UsersController;
use App\Http\Controllers\APIS\AdminApi\DeviceController;
use App\Http\Controllers\APIS\CustomerApi\TelemetryController;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Route;
use App\Http\Controllers\APIS\AdminApi\AssetadmintController;
@@ -44,13 +45,13 @@ Route::post('/customer/delete', [CustomerController::class, 'deleteCustomers'])-
Route::post('/users-store', [UsersController::class, 'store'])->name('user_create');
Route::get('/users-list', [UsersController::class, 'list'])->name('user_list');
Route::post('/users-delete', [UsersController::class, 'delete']);
Route::get('/activate/{id}', [UsersController::class, 'activate'])->name('activate.user');
Route::post('/activate/{id}/{token}', [UsersController::class, 'activate'])->name('activate.user');
Route::post('/users-login', [UsersController::class, 'loginUser']);
Route::post('/users-customer-list', [UsersController::class, 'userlistCustomer'])->name('usertList.customer');
Route::get('/users/{customer_id}', [UsersController::class, 'UserByCustomerId'])->name('usertList.customerId');
//******************************************************* Device API********************************************************
Route::post('/device/create-or-update', [DeviceController::class, 'createOrUpdateDevice'])->name('device.create-or-update');
Route::post('/device/create-or-update', [DeviceController::class, 'createOrUpdateDevice']);
Route::get('/device/list', [DeviceController::class, 'listDevices'])->name('device.list');
Route::post('/device/delete', [DeviceController::class, 'deleteDevice'])->name('device.delete');
Route::get('/device/{customer_id}', [DeviceController::class, 'devicelistCustomer'])->name('devicetList.customer');
@@ -67,7 +68,8 @@ Route::get('/alarm/{id}', [AlarmControllerCommon::class, 'getAlarmById'])->name(
Route::post('/alarm/ack/{id}', [AlarmControllerCommon::class, 'acknowledgeAlarmById'])->name('ack.alarm');
Route::post('/alarm/filter', [AlarmControllerCommon::class, 'filterAlarm'])->name('alarm.filter');
Route::post('/alarm/clear/{id}', [AlarmControllerCommon::class, 'clearAlarmById'])->name('clear.alarm');
Route::post('/get-admin-alarms', [TelemetryController::class, 'getAdminAlarms']);
Route::get('get-device-by-asset/{assetId}', [TelemetryController::class, 'getDeviceByAsset']);
//******************************************************* Rule Chain API ********************************************************
Route::get('/rule-chains', [RuleChainController::class, 'getRuleChainList'])->name('list.RuleChain');

View File

@@ -5,7 +5,7 @@ use Illuminate\Support\Facades\Route;
use App\Http\Controllers\APIS\CustomerApi\UserAssetLinkController;
use Tymon\JWTAuth\Facades\JWTAuth;
use App\Http\Controllers\AlarmControllerCommon;
use App\Http\Controllers\APIS\AdminApi\UsersController;
use App\Http\Controllers\APIS\CustomerApi\AuthController;
use App\Http\Controllers\APIS\CustomerApi\CustomerDeviceInfoController;
use App\Http\Controllers\APIS\CustomerApi\TelemetryController;
@@ -25,19 +25,18 @@ Route::post('/telemetry-data-device-diagnostic', [TelemetryController::class, 't
// Route::post('/user-login', [AuthController::class, 'login']);
Route::middleware(['customerApiBasicAuth'])->group(function () {
Route::get('/user-assets', [UserAssetLinkController::class, 'index']);
Route::get('/customer-device-info', [CustomerDeviceInfoController::class, 'customerDeviceInfo']);
Route::get('/user-assets-old', [UserAssetLinkController::class, 'index']);
Route::get('/customer-device-info-old', [CustomerDeviceInfoController::class, 'customerDeviceInfo']);
Route::get('/user-info', [CustomerDeviceInfoController::class, 'userInfo']);
Route::post('/telemetry-data-asset', [TelemetryController::class, 'telemetryDataAsset']);
Route::post('/telemetry-data-device', [TelemetryController::class, 'telemetryDataDevice']);
Route::get('/user-assets', [UserAssetLinkController::class, 'index']);
Route::post('/store/report', [CustomerApiDownloadsController::class, 'storePdfData'])->name('store-report');
Route::post('/fetch/report', [CustomerApiDownloadsController::class, 'fetchReport'])->name('fetch-report');
Route::post('/destroy/report', [CustomerApiDownloadsController::class, 'destroyReport'])->name('destroy-report');
Route::get('/alert-message/{deviceId}', [TimeseriesAlertMessageController::class, 'alertMessage']);
Route::get('/user-assets', [UserAssetLinkController::class, 'index']);
Route::post('/store/report', [CustomerApiDownloadsController::class, 'storePdfData'])->name('store-report');
Route::post('/fetch/report', [CustomerApiDownloadsController::class, 'fetchReport'])->name('fetch-report');
Route::post('/destroy/report', [CustomerApiDownloadsController::class, 'destroyReport'])->name('destroy-report');
@@ -49,10 +48,27 @@ Route::middleware(['customerApiBasicAuth'])->group(function () {
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('/user-assets', [TelemetryController::class, 'userAssetsNew']);
Route::get('/customer-device-info', [TelemetryController::class, 'customerDeviceInfoNew']);
Route::get('/get-active-devices-list', [TelemetryController::class, 'getActiveDevicesList']);
Route::get('/get-device-indicators/{assetId}', [TelemetryController::class, 'getDeviceIndicators']);
Route::get('/get-live-device/{deviceId}', [TelemetryController::class, 'getLiveDevice']);
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']);
Route::get('/get-cylinder-specific-indicators/{deviceId}', [TelemetryController::class, 'getCylinderSpecificIndicators']);
Route::get('/get-peak-pressure/{deviceId}', [TelemetryController::class, 'getPeakPressure']);
// Alarms
Route::post('/get-user-alarms', [TelemetryController::class, 'getUserAlarms']);
Route::get('/get-user-device-by-asset/{assetId}', [TelemetryController::class, 'getUserDeviceByAsset']);
Route::get('/get-user-assets', [TelemetryController::class, 'getUserAssets']);
});
// user password update
Route::post('/user-password-update-link', [UsersController::class, 'userEmailCheck']);
Route::post('/user-password-update', [UsersController::class, 'userUpdatePassword'])->name('user.password.update');